diff --git a/docs/docs/components/universal/_meta.json b/docs/docs/components/universal/_meta.json index 7c450c5..c6420fd 100644 --- a/docs/docs/components/universal/_meta.json +++ b/docs/docs/components/universal/_meta.json @@ -3,5 +3,6 @@ "button", "accordion", "input", - "badge" + "badge", + "calendar" ] \ No newline at end of file diff --git a/docs/docs/components/universal/accordion.mdx b/docs/docs/components/universal/accordion.mdx index 6371f4b..3de74a0 100644 --- a/docs/docs/components/universal/accordion.mdx +++ b/docs/docs/components/universal/accordion.mdx @@ -28,7 +28,7 @@ Accordion component allows you to expand and collapse content. ``` -## Try it out +## Example ```jsx import React from 'react'; diff --git a/docs/docs/components/universal/badge.mdx b/docs/docs/components/universal/badge.mdx index bab732c..6d2a06d 100644 --- a/docs/docs/components/universal/badge.mdx +++ b/docs/docs/components/universal/badge.mdx @@ -35,22 +35,33 @@ export default function App() { ### Example -```jsx playground direction=vertical +```jsx import { Badge } from "@sast/ui-universal"; export default function Example() { - const handleCopy = () => { - console.log("Badge content copied!"); - }; - return ( + <> + + + + ); } ``` \ No newline at end of file diff --git a/docs/docs/components/universal/button.mdx b/docs/docs/components/universal/button.mdx index f0014e2..7b4a4ab 100644 --- a/docs/docs/components/universal/button.mdx +++ b/docs/docs/components/universal/button.mdx @@ -1,12 +1,12 @@ import Wraper from '../../tools/wraper/index' -import {Button} from '@sast/ui-universal' +import { Button } from '@sast/ui-universal' # Button Component Simple button component - @@ -23,15 +23,15 @@ Simple button component | `disabled` | If `true`, the button will be disabled. | `boolean` | `false` | | `disabledShadow` | When the button is disabled, specifies whether the shadow should be applied or not. | `boolean` | `true` | -## Try it out +## Example -```jsx playground direction=vertical +```jsx import React from 'react'; import {Button} from '@sast/ui-universal' export default function App (){ return ( - ) diff --git a/docs/docs/components/universal/calendar.mdx b/docs/docs/components/universal/calendar.mdx new file mode 100644 index 0000000..9a09f03 --- /dev/null +++ b/docs/docs/components/universal/calendar.mdx @@ -0,0 +1,39 @@ +import Wraper from '../../tools/wraper/index' +import { Calendar } from '@sast/ui-universal' + +# Calendar Component + +The Calendar component allows users to select dates and navigate through months. + + +
+ console.log(date)} /> +
+
+ + +## Props + +| Property | Description | Type | Default | +|-------------------|-----------------------------------------------|---------------------------|---------| +| `onSelect` | Callback function triggered when a date is selected. | `(value: Date) => void` | | +| `selected` | The currently selected date. | `Date \| undefined` | | + +## Events + +- `onSelect`: Fired when a date is selected. Provides the selected date as an argument to the callback function. + +## Example + +```jsx +import {Calendar} from '@sast/ui-universal' + +export default function Example() { + const handleSelect = (date) => { + console.log("Selected date:", date); + }; + + return
; +} +``` + diff --git a/docs/docs/components/universal/input.mdx b/docs/docs/components/universal/input.mdx index a1c22c6..5fceb85 100644 --- a/docs/docs/components/universal/input.mdx +++ b/docs/docs/components/universal/input.mdx @@ -34,9 +34,9 @@ Input component allows users to input text or passwords. > ``` -## How to fire events +## Example in React -```jsx playground direction=vertical +```jsx import React, {useRef} from 'react'; import { Input, Button } from '@sast/ui-universal'; @@ -68,11 +68,10 @@ export default function App () { disabled={disable} />
- - + +
); } - ``` \ No newline at end of file diff --git a/docs/rspress.config.ts b/docs/rspress.config.ts index d817de3..11de513 100644 --- a/docs/rspress.config.ts +++ b/docs/rspress.config.ts @@ -1,14 +1,16 @@ import * as path from "path"; import { defineConfig } from "rspress/config"; import { pluginPlayground } from "@rspress/plugin-playground"; +import { pluginPreview } from "@rspress/plugin-preview"; import { remarkMermaid } from "@theguild/remark-mermaid"; export default defineConfig({ plugins: [ - pluginPlayground({ - include: ["@sast/ui-universal"], - defaultRenderMode: "pure", - }), + // pluginPlayground({ + // include: ["@sast/ui-universal"], + // defaultRenderMode: "pure", + // }), + pluginPreview( ), ], globalUIComponents: [ path.join(__dirname, "docs", "tools", "wraper", "index.tsx"), diff --git a/packages/ui-react/lib/Calendar/Calendar.module.scss b/packages/ui-react/lib/Calendar/Calendar.module.scss index 15a9d90..9695d96 100644 --- a/packages/ui-react/lib/Calendar/Calendar.module.scss +++ b/packages/ui-react/lib/Calendar/Calendar.module.scss @@ -8,6 +8,7 @@ $animation-duration: $duration-300; background-color: var(--white-color); color: var(--black-color); box-shadow: $shadow; + min-width: 19.6875rem; .calendarTitle { font-size: 18px; font-weight: 1000; diff --git a/packages/ui-universal/lib/_variables.scss b/packages/ui-universal/lib/_variables.scss index 3b3fecc..74be33c 100644 --- a/packages/ui-universal/lib/_variables.scss +++ b/packages/ui-universal/lib/_variables.scss @@ -1,10 +1,19 @@ @use "./global.scss" as *; + // box-shadow variables $shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); -$shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); -$shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); -$shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); -$shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); +$shadow: + 0 1px 3px 0 rgba(0, 0, 0, 0.1), + 0 1px 2px -1px rgba(0, 0, 0, 0.1); +$shadow-md: + 0 4px 6px -1px rgb(0 0 0 / 0.1), + 0 2px 4px -2px rgb(0 0 0 / 0.1); +$shadow-lg: + 0 10px 15px -3px rgb(0 0 0 / 0.1), + 0 4px 6px -4px rgb(0 0 0 / 0.1); +$shadow-xl: + 0 20px 25px -5px rgb(0 0 0 / 0.1), + 0 8px 10px -6px rgb(0 0 0 / 0.1); $shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); $shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); @@ -29,25 +38,6 @@ $shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); } } -// border width variables -$border-0: 0px; -$border-1: 1px; -$border-2: 2px; - -//animation-duration varibles -$duration-100: 100ms; -$duration-200: 200ms; -$duration-300: 300ms; -$duration-400: 400ms; -$duration-800: 800ms; - -//border radius variables -$radius-10: 10px; -$radius-8: 8px; -$radius-5: 5px; -$radius-15: 15px; -$radius-half: 50%; - //absolute center @mixin absolute-center { position: absolute; @@ -56,20 +46,5 @@ $radius-half: 50%; transform: translate(-50%, -50%); } -//font-size variables -$font-size-8: 8px; -$font-size-10: 10px; -$font-size-12: 12px; -$font-size-14: 14px; -$font-size-16: 16px; - -//disabled -@mixin disabled { - cursor: not-allowed; - opacity: 0.4; -} - //background color $background-shadow-color: rgb(var(--black-color-rgb), 0.6); - -$cubic-bezier: cubic-bezier(0.215, 0.61, 0.355, 1); diff --git a/packages/ui-universal/lib/_variables/radius.scss b/packages/ui-universal/lib/_variables/radius.scss index cb6e5e4..a45d03d 100644 --- a/packages/ui-universal/lib/_variables/radius.scss +++ b/packages/ui-universal/lib/_variables/radius.scss @@ -3,4 +3,4 @@ $radius-10: 10px; $radius-8: 8px; $radius-5: 5px; $radius-15: 15px; -$radius-half: 50%; +$radius-half: 50%; \ No newline at end of file diff --git a/packages/ui-universal/lib/components/Accordion/index.scss b/packages/ui-universal/lib/components/Accordion/index.scss index f9dec73..368349f 100644 --- a/packages/ui-universal/lib/components/Accordion/index.scss +++ b/packages/ui-universal/lib/components/Accordion/index.scss @@ -1,4 +1,12 @@ -@use '../../variables' as *; +@use "../../variables" as *; +@use "../../_variables/color.scss" as *; +@use "../../_variables/radius.scss" as *; +@use "../../_variables/border.scss" as *; +@use "../../_variables/fontSize.scss" as *; +@use "../../_variables/duration.scss" as *; +@use "../../_variables/animation.scss" as *; +@use "../../_variables/disabled.scss" as *; + $animation-duration: $duration-300; .base { display: grid; diff --git a/packages/ui-universal/lib/components/Badge/index.scss b/packages/ui-universal/lib/components/Badge/index.scss index 3b807aa..3e61cac 100644 --- a/packages/ui-universal/lib/components/Badge/index.scss +++ b/packages/ui-universal/lib/components/Badge/index.scss @@ -1,3 +1,5 @@ +@use "../../variables" as *; + @mixin color-badge($color-name) { background-color: rgba(var(--#{$color-name}-color-background-rgb), 1); color: var(--#{$color-name}-color); @@ -6,7 +8,7 @@ .base { padding: 3px 10px; border-radius: 5px; - width: fit-content; + display: inline-flex; &.info { @include color-badge(primary); diff --git a/packages/ui-universal/lib/components/Badge/index.ts b/packages/ui-universal/lib/components/Badge/index.ts index b619bf3..fd922bc 100644 --- a/packages/ui-universal/lib/components/Badge/index.ts +++ b/packages/ui-universal/lib/components/Badge/index.ts @@ -36,7 +36,6 @@ class ABadge extends LitElement { return html`
diff --git a/packages/ui-universal/lib/components/Calendar/index.scss b/packages/ui-universal/lib/components/Calendar/index.scss new file mode 100644 index 0000000..756973a --- /dev/null +++ b/packages/ui-universal/lib/components/Calendar/index.scss @@ -0,0 +1,87 @@ +@use "../../variables" as *; +@use "../../_variables/color.scss" as *; +@use "../../_variables/radius.scss" as *; +@use "../../_variables/border.scss" as *; +@use "../../_variables/fontSize.scss" as *; +@use "../../_variables/duration.scss" as *; +@use "../../_variables/animation.scss" as *; +@use "../../_variables/disabled.scss" as *; +$animation-duration: $duration-300; +.base { + height: fit-content; + width: fit-content; + padding: 10px; + border-radius: $radius-10; + background-color: var(--white-color); + color: var(--black-color); + box-shadow: $shadow; + min-width: 19.6875rem; + .calendarTitle { + font-size: 18px; + font-weight: 1000; + color: var(--shadow-color); + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 8px 10px; + .buttonContainer { + display: flex; + gap: 3px; + } + } + .calendarItems { + display: grid; + grid-template-columns: repeat(7, 1fr); + grid-template-rows: 1.5fr auto; + column-gap: 5px; + row-gap: 5px; + padding: 5px 10px; + box-sizing: border-box; + justify-items: center; + .calendarItem { + display: flex; + align-items: center; + justify-content: center; + width: 35px; + height: 35px; + cursor: pointer; + &.otherMonth { + opacity: 0.4; + } + &:hover:not(&.today):not(&.select) { + background-color: var(--background-blue); + color: var(--primary-color); + border-radius: $radius-5; + transition: all $animation-duration $cubic-bezier; + } + &.select { + background-color: var(--primary-color); + border-radius: 5px; + color: var(--white-color); + transition: all $animation-duration $cubic-bezier; + } + &.today { + background-color: var(--background-blue); + color: var(--primary-color); + border-radius: $radius-5; + } + } + } + .weekdays { + display: grid; + grid-template-columns: repeat(7, 1fr); + background-color: var(--title-shadow); + box-sizing: border-box; + gap: 5px; + padding: 10px; + border-radius: 5px; + font-weight: 600; + color: var(--shadow-color); + .weekday { + font-size: $font-size-14; + width: 35px; + text-align: center; + } + } +} diff --git a/packages/ui-universal/lib/components/Calendar/index.ts b/packages/ui-universal/lib/components/Calendar/index.ts new file mode 100644 index 0000000..347eaa2 --- /dev/null +++ b/packages/ui-universal/lib/components/Calendar/index.ts @@ -0,0 +1,234 @@ +import { LitElement, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { createComponent } from "@lit/react"; +import React from "react"; +import styles from "./index.scss?inline"; +import { classMap } from "lit/directives/class-map.js"; + +export interface CalendarProps { + /** + * the onChange of the calendar + */ + onchange?: (value: Date) => void; + /** + * the selected of the date + */ + selected?: Date; +} + +@customElement("a-calendar") +export class ACalendar extends LitElement { + static styles = styles; + @property() onSelect?: (value: Date) => void; + @property({ type: Object }) selected?: Date; + + @state() private selectDate: Date | undefined; + @state() private currentDate: Date = new Date(); + @state() private selectMonth: number = new Date().getMonth(); + @state() private numberOfDaysFromPrevMonth: number = 0; + @state() private numberOfDaysInLastMonth: number = 0; + @state() private numberOfDaysInMonth: number = 0; + @state() private numberOfDaysFromAfterMonth: number = 0; + + updated(changedProperties: Map) { + if (changedProperties.has("selected")) { + this.selectDate = this.selected; + } + } + + firstUpdated() { + this.updateCalendar(); + } + + // update number of days in month + private updateNumberOfDaysInMonth() { + this.numberOfDaysInMonth = new Date( + this.currentDate.getFullYear(), + this.selectMonth + 1, + 0 + ).getDate(); + } + + // update number of days from prev month + private updateNumberOfDaysFromPrevMonth() { + const firstDay = new Date( + this.currentDate.getFullYear(), + this.selectMonth, + 1 + ).getDay(); + this.numberOfDaysFromPrevMonth = firstDay === 0 ? 6 : firstDay - 1; + } + + // update number of days from after month + private updateNumberOfDaysFromAfterMonth() { + const lastDay = new Date( + this.currentDate.getFullYear(), + this.selectMonth + 1, + 0 + ).getDay(); + this.numberOfDaysFromAfterMonth = lastDay === 0 ? 0 : 7 - lastDay; + } + + // update number of days in last month + private updateNumberOfDaysInLastMonth() { + this.numberOfDaysInLastMonth = new Date( + this.currentDate.getFullYear(), + this.selectMonth, + 0 + ).getDate(); + } + + private updateCalendar() { + this.updateNumberOfDaysInMonth(); + this.updateNumberOfDaysFromPrevMonth(); + this.updateNumberOfDaysFromAfterMonth(); + this.updateNumberOfDaysInLastMonth(); + } + + private changeMonth(isBack: boolean) { + this.selectMonth = isBack ? this.selectMonth - 1 : this.selectMonth + 1; + this.updateCalendar(); + } + + private generateCalendarGrid() { + const dayItems = []; + for (let index = 0; index < this.numberOfDaysFromPrevMonth; index++) { + dayItems.push( + html`
+ ${this.numberOfDaysInLastMonth - + this.numberOfDaysFromPrevMonth + + index + + 1} +
` + ); + } + for (let index = 0; index < this.numberOfDaysInMonth; index++) { + dayItems.push( + html`
{ + this.selected = new Date( + this.currentDate.getFullYear(), + this.selectMonth, + index + 1 + ); + this.onSelect && this.onSelect(this.selected); + }} + > + ${index + 1} +
` + ); + } + for (let index = 0; index < this.numberOfDaysFromAfterMonth; index++) { + dayItems.push( + html`
${index + 1}
` + ); + } + return dayItems; + } + + render() { + return html` +
+
+
+ this.changeMonth(true)} + color="border" + size="small" + class="button" + > + + + + + + this.changeMonth(false)} + color="border" + size="small" + class="button" + > + + + + + +
+ ${new Date(this.currentDate.getFullYear(), this.selectMonth + 1, 0) + .toDateString() + .split(" ")[1]}, + ${this.currentDate.getFullYear()} +
+
+
Mo
+
Tu
+
We
+
Th
+
Fr
+
Sa
+
Su
+
+
+ ${this.generateCalendarGrid().map((value) => { + return value; + })} +
+
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "a-calendar": ACalendar; + } +} + +export const Calendar = createComponent({ + tagName: "a-calendar", + elementClass: ACalendar, + react: React, +}); diff --git a/packages/ui-universal/lib/components/Input/index.scss b/packages/ui-universal/lib/components/Input/index.scss index c3ff70c..4fbf8e7 100644 --- a/packages/ui-universal/lib/components/Input/index.scss +++ b/packages/ui-universal/lib/components/Input/index.scss @@ -1,5 +1,11 @@ @use "../../variables" as *; @use "../../_variables/color.scss" as *; +@use "../../_variables/radius.scss" as *; +@use "../../_variables/border.scss" as *; +@use "../../_variables/fontSize.scss" as *; +@use "../../_variables/duration.scss" as *; +@use "../../_variables/animation.scss" as *; +@use "../../_variables/disabled.scss" as *; $border-radius: $radius-8; $border-width: $border-1; diff --git a/packages/ui-universal/lib/index.ts b/packages/ui-universal/lib/index.ts index 909bd38..1ee1301 100644 --- a/packages/ui-universal/lib/index.ts +++ b/packages/ui-universal/lib/index.ts @@ -2,3 +2,4 @@ export * from "./components/Button"; export * from "./components/Accordion"; export * from "./components/Input"; export * from "./components/Badge"; +export * from "./components/Calendar"; diff --git a/packages/ui-universal/vite.config.js b/packages/ui-universal/vite.config.js index 14914b7..4e772c0 100644 --- a/packages/ui-universal/vite.config.js +++ b/packages/ui-universal/vite.config.js @@ -22,7 +22,6 @@ export default { css: { preprocessorOptions: { scss: { - additionalData: `@use "./lib/variables" as *;`, // Import global scss variables includePaths: [path.resolve(__dirname, "lib")], // Include paths for scss }, },