@grampro/kit 0.0.0-stage → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gbs/skills/gbs-components/SKILL.md +190 -0
- package/.gbs/skills/gbs-components/references/accessibility.md +102 -0
- package/.gbs/skills/gbs-components/references/data-display.md +185 -0
- package/.gbs/skills/gbs-components/references/data-grid.md +116 -0
- package/.gbs/skills/gbs-components/references/forms.md +202 -0
- package/.gbs/skills/gbs-components/references/install.md +211 -0
- package/.gbs/skills/gbs-components/references/overlays.md +206 -0
- package/.gbs/skills/gbs-components/references/pickers.md +83 -0
- package/.gbs/skills/gbs-components/references/styling.md +246 -0
- package/.gbs/skills/gbs-components/references/toaster.md +57 -0
- package/CHANGELOG.md +139 -0
- package/LICENSE +15 -0
- package/README.md +193 -2
- package/index.cjs +1370 -0
- package/package.json +74 -4
- package/schema/passport-v1.schema.json +204 -0
- package/source/components/accordion/README.md +45 -0
- package/source/components/accordion/core/index.ts +2 -0
- package/source/components/accordion/core/open.ts +56 -0
- package/source/components/accordion/core/types.ts +17 -0
- package/source/components/accordion/index.ts +8 -0
- package/source/components/accordion/passport.json +259 -0
- package/source/components/accordion/react/Accordion.tsx +133 -0
- package/source/components/accordion/react/AccordionItem.tsx +120 -0
- package/source/components/accordion/react/context.ts +20 -0
- package/source/components/accordion/react/props.ts +13 -0
- package/source/components/accordion/styles.css +207 -0
- package/source/components/alert/README.md +39 -0
- package/source/components/alert/core/index.ts +2 -0
- package/source/components/alert/core/live.ts +25 -0
- package/source/components/alert/core/types.ts +7 -0
- package/source/components/alert/index.ts +5 -0
- package/source/components/alert/passport.json +250 -0
- package/source/components/alert/react/Alert.tsx +113 -0
- package/source/components/alert/react/icons.tsx +21 -0
- package/source/components/alert/react/locale.ts +5 -0
- package/source/components/alert/react/props.ts +11 -0
- package/source/components/alert/styles.css +154 -0
- package/source/components/avatar/core/identity.ts +103 -0
- package/source/components/avatar/core/index.ts +2 -0
- package/source/components/avatar/core/types.ts +12 -0
- package/source/components/avatar/index.ts +7 -0
- package/source/components/avatar/passport.json +294 -0
- package/source/components/avatar/react/Avatar.tsx +118 -0
- package/source/components/avatar/react/AvatarGroup.tsx +74 -0
- package/source/components/avatar/react/locale.ts +11 -0
- package/source/components/avatar/react/props.ts +6 -0
- package/source/components/avatar/styles.css +225 -0
- package/source/components/badge/README.md +37 -0
- package/source/components/badge/core/count.ts +37 -0
- package/source/components/badge/core/index.ts +2 -0
- package/source/components/badge/core/types.ts +11 -0
- package/source/components/badge/index.ts +7 -0
- package/source/components/badge/passport.json +332 -0
- package/source/components/badge/react/Badge.tsx +89 -0
- package/source/components/badge/react/Tag.tsx +82 -0
- package/source/components/badge/react/locale.ts +5 -0
- package/source/components/badge/react/props.ts +6 -0
- package/source/components/badge/styles.css +203 -0
- package/source/components/breadcrumb/README.md +34 -0
- package/source/components/breadcrumb/core/index.ts +4 -0
- package/source/components/breadcrumb/core/trail.ts +42 -0
- package/source/components/breadcrumb/core/types.ts +20 -0
- package/source/components/breadcrumb/index.ts +5 -0
- package/source/components/breadcrumb/passport.json +243 -0
- package/source/components/breadcrumb/react/Breadcrumb.tsx +177 -0
- package/source/components/breadcrumb/react/locale.ts +6 -0
- package/source/components/breadcrumb/react/props.ts +14 -0
- package/source/components/breadcrumb/styles.css +138 -0
- package/source/components/button/README.md +32 -0
- package/source/components/button/core/index.ts +3 -0
- package/source/components/button/core/state.ts +16 -0
- package/source/components/button/core/types.ts +28 -0
- package/source/components/button/index.ts +5 -0
- package/source/components/button/passport.json +402 -0
- package/source/components/button/passport.manual.json +31 -0
- package/source/components/button/react/Button.tsx +173 -0
- package/source/components/button/react/locale.ts +5 -0
- package/source/components/button/react/props.ts +23 -0
- package/source/components/button/styles.css +232 -0
- package/source/components/card/README.md +60 -0
- package/source/components/card/core/index.ts +4 -0
- package/source/components/card/core/trend.ts +32 -0
- package/source/components/card/core/types.ts +5 -0
- package/source/components/card/index.ts +5 -0
- package/source/components/card/passport.json +337 -0
- package/source/components/card/react/Card.tsx +133 -0
- package/source/components/card/react/Stat.tsx +127 -0
- package/source/components/card/react/props.ts +4 -0
- package/source/components/card/styles.css +230 -0
- package/source/components/checkbox/README.md +36 -0
- package/source/components/checkbox/core/group.ts +30 -0
- package/source/components/checkbox/core/index.ts +3 -0
- package/source/components/checkbox/core/types.ts +17 -0
- package/source/components/checkbox/index.ts +9 -0
- package/source/components/checkbox/passport.json +456 -0
- package/source/components/checkbox/react/Checkbox.tsx +147 -0
- package/source/components/checkbox/react/CheckboxGroup.tsx +149 -0
- package/source/components/checkbox/react/context.ts +16 -0
- package/source/components/checkbox/react/locale.ts +5 -0
- package/source/components/checkbox/react/props.ts +6 -0
- package/source/components/checkbox/styles.css +211 -0
- package/source/components/combobox/README.md +170 -0
- package/source/components/combobox/core/filter.ts +155 -0
- package/source/components/combobox/core/index.ts +16 -0
- package/source/components/combobox/core/types.ts +48 -0
- package/source/components/combobox/core/virtual.ts +67 -0
- package/source/components/combobox/index.ts +13 -0
- package/source/components/combobox/passport.json +456 -0
- package/source/components/combobox/react/Listbox.tsx +310 -0
- package/source/components/combobox/react/MultiSelect.tsx +265 -0
- package/source/components/combobox/react/Popover.tsx +38 -0
- package/source/components/combobox/react/Select.tsx +200 -0
- package/source/components/combobox/react/icons.tsx +11 -0
- package/source/components/combobox/react/locale.ts +16 -0
- package/source/components/combobox/react/props.ts +88 -0
- package/source/components/combobox/react/useCombobox.ts +409 -0
- package/source/components/combobox/styles.css +419 -0
- package/source/components/data-grid/README.md +233 -0
- package/source/components/data-grid/agent/coerce.ts +368 -0
- package/source/components/data-grid/agent/contract.ts +410 -0
- package/source/components/data-grid/agent/dataset.ts +92 -0
- package/source/components/data-grid/agent/engine.ts +470 -0
- package/source/components/data-grid/agent/executors.ts +155 -0
- package/source/components/data-grid/agent/index.ts +79 -0
- package/source/components/data-grid/agent/intent.ts +324 -0
- package/source/components/data-grid/agent/operations.ts +335 -0
- package/source/components/data-grid/agent/validate.ts +630 -0
- package/source/components/data-grid/agent/webmcp.ts +107 -0
- package/source/components/data-grid/core/columnHelper.ts +21 -0
- package/source/components/data-grid/core/columns.ts +288 -0
- package/source/components/data-grid/core/filtering.ts +237 -0
- package/source/components/data-grid/core/grid.ts +638 -0
- package/source/components/data-grid/core/index.ts +14 -0
- package/source/components/data-grid/core/rows.ts +64 -0
- package/source/components/data-grid/core/sorting.ts +133 -0
- package/source/components/data-grid/core/state.ts +82 -0
- package/source/components/data-grid/core/store.ts +52 -0
- package/source/components/data-grid/core/types.ts +302 -0
- package/source/components/data-grid/core/values.ts +98 -0
- package/source/components/data-grid/core/virtual.ts +85 -0
- package/source/components/data-grid/export/csv.ts +32 -0
- package/source/components/data-grid/export/download.ts +12 -0
- package/source/components/data-grid/export/pdf-font.ts +139 -0
- package/source/components/data-grid/export/pdf-writer.ts +113 -0
- package/source/components/data-grid/export/pdf.ts +379 -0
- package/source/components/data-grid/export/table.ts +73 -0
- package/source/components/data-grid/export/xlsx.ts +145 -0
- package/source/components/data-grid/export/zip.ts +87 -0
- package/source/components/data-grid/index.ts +14 -0
- package/source/components/data-grid/passport.json +1051 -0
- package/source/components/data-grid/passport.manual.json +255 -0
- package/source/components/data-grid/react/AskGrid.tsx +164 -0
- package/source/components/data-grid/react/Cell.tsx +282 -0
- package/source/components/data-grid/react/ColumnMenu.tsx +135 -0
- package/source/components/data-grid/react/DataGrid.tsx +335 -0
- package/source/components/data-grid/react/FilterForm.tsx +142 -0
- package/source/components/data-grid/react/HeaderRow.tsx +332 -0
- package/source/components/data-grid/react/Pagination.tsx +107 -0
- package/source/components/data-grid/react/Popover.tsx +35 -0
- package/source/components/data-grid/react/Row.tsx +85 -0
- package/source/components/data-grid/react/Toolbar.tsx +267 -0
- package/source/components/data-grid/react/Viewport.tsx +167 -0
- package/source/components/data-grid/react/context.ts +57 -0
- package/source/components/data-grid/react/hooks.ts +83 -0
- package/source/components/data-grid/react/icons.tsx +45 -0
- package/source/components/data-grid/react/keyboard.ts +110 -0
- package/source/components/data-grid/react/locale.ts +130 -0
- package/source/components/data-grid/styles.css +874 -0
- package/source/components/date-picker/README.md +141 -0
- package/source/components/date-picker/core/calendar.ts +266 -0
- package/source/components/date-picker/core/format.ts +170 -0
- package/source/components/date-picker/core/index.ts +41 -0
- package/source/components/date-picker/core/today.ts +72 -0
- package/source/components/date-picker/core/types.ts +68 -0
- package/source/components/date-picker/index.ts +16 -0
- package/source/components/date-picker/passport.json +407 -0
- package/source/components/date-picker/react/Calendar.tsx +160 -0
- package/source/components/date-picker/react/CalendarPanel.tsx +170 -0
- package/source/components/date-picker/react/DatePicker.tsx +249 -0
- package/source/components/date-picker/react/DateRangePicker.tsx +291 -0
- package/source/components/date-picker/react/MonthYearPanels.tsx +123 -0
- package/source/components/date-picker/react/Popover.tsx +45 -0
- package/source/components/date-picker/react/icons.tsx +15 -0
- package/source/components/date-picker/react/locale.ts +23 -0
- package/source/components/date-picker/react/props.ts +76 -0
- package/source/components/date-picker/react/useDatePicker.ts +557 -0
- package/source/components/date-picker/styles.css +445 -0
- package/source/components/dialog/README.md +39 -0
- package/source/components/dialog/core/api.ts +34 -0
- package/source/components/dialog/core/dialog.ts +11 -0
- package/source/components/dialog/core/index.ts +7 -0
- package/source/components/dialog/core/store.ts +81 -0
- package/source/components/dialog/core/types.ts +59 -0
- package/source/components/dialog/index.ts +7 -0
- package/source/components/dialog/passport.json +344 -0
- package/source/components/dialog/react/Dialog.tsx +279 -0
- package/source/components/dialog/react/DialogHost.tsx +45 -0
- package/source/components/dialog/react/icons.tsx +20 -0
- package/source/components/dialog/react/locale.ts +8 -0
- package/source/components/dialog/react/props.ts +13 -0
- package/source/components/dialog/styles.css +280 -0
- package/source/components/file-uploader/README.md +99 -0
- package/source/components/file-uploader/core/format.ts +79 -0
- package/source/components/file-uploader/core/index.ts +26 -0
- package/source/components/file-uploader/core/store.ts +432 -0
- package/source/components/file-uploader/core/transport.ts +154 -0
- package/source/components/file-uploader/core/types.ts +126 -0
- package/source/components/file-uploader/core/validate.ts +83 -0
- package/source/components/file-uploader/index.ts +7 -0
- package/source/components/file-uploader/passport.json +518 -0
- package/source/components/file-uploader/react/FileRow.tsx +268 -0
- package/source/components/file-uploader/react/FileUploader.tsx +511 -0
- package/source/components/file-uploader/react/icons.tsx +60 -0
- package/source/components/file-uploader/react/locale.ts +33 -0
- package/source/components/file-uploader/react/props.ts +31 -0
- package/source/components/file-uploader/react/useFileUploader.ts +32 -0
- package/source/components/file-uploader/styles.css +394 -0
- package/source/components/input/README.md +44 -0
- package/source/components/input/core/count.ts +5 -0
- package/source/components/input/core/index.ts +11 -0
- package/source/components/input/core/otp.ts +64 -0
- package/source/components/input/core/types.ts +14 -0
- package/source/components/input/index.ts +8 -0
- package/source/components/input/passport.json +536 -0
- package/source/components/input/react/Input.tsx +219 -0
- package/source/components/input/react/OtpInput.tsx +256 -0
- package/source/components/input/react/dom.ts +10 -0
- package/source/components/input/react/icons.tsx +17 -0
- package/source/components/input/react/locale.ts +9 -0
- package/source/components/input/react/props.ts +6 -0
- package/source/components/input/styles.css +295 -0
- package/source/components/menu/README.md +68 -0
- package/source/components/menu/core/index.ts +11 -0
- package/source/components/menu/core/navigation.ts +84 -0
- package/source/components/menu/core/types.ts +32 -0
- package/source/components/menu/index.ts +19 -0
- package/source/components/menu/passport.json +322 -0
- package/source/components/menu/react/Menu.tsx +371 -0
- package/source/components/menu/react/context.ts +31 -0
- package/source/components/menu/react/items.tsx +268 -0
- package/source/components/menu/react/locale.ts +6 -0
- package/source/components/menu/react/props.ts +4 -0
- package/source/components/menu/react/useMenuKeys.ts +124 -0
- package/source/components/menu/styles.css +224 -0
- package/source/components/modal/README.md +51 -0
- package/source/components/modal/core/dismiss.ts +29 -0
- package/source/components/modal/core/index.ts +3 -0
- package/source/components/modal/core/types.ts +27 -0
- package/source/components/modal/index.ts +5 -0
- package/source/components/modal/passport.json +289 -0
- package/source/components/modal/react/Modal.tsx +242 -0
- package/source/components/modal/react/icons.tsx +1 -0
- package/source/components/modal/react/locale.ts +5 -0
- package/source/components/modal/react/props.ts +17 -0
- package/source/components/modal/styles.css +241 -0
- package/source/components/number-input/README.md +53 -0
- package/source/components/number-input/core/format.ts +37 -0
- package/source/components/number-input/core/index.ts +4 -0
- package/source/components/number-input/core/parse.ts +118 -0
- package/source/components/number-input/core/step.ts +73 -0
- package/source/components/number-input/core/types.ts +32 -0
- package/source/components/number-input/index.ts +5 -0
- package/source/components/number-input/passport.json +541 -0
- package/source/components/number-input/react/NumberInput.tsx +465 -0
- package/source/components/number-input/react/icons.tsx +17 -0
- package/source/components/number-input/react/locale.ts +7 -0
- package/source/components/number-input/react/props.ts +11 -0
- package/source/components/number-input/styles.css +230 -0
- package/source/components/popover/README.md +44 -0
- package/source/components/popover/core/index.ts +2 -0
- package/source/components/popover/core/types.ts +12 -0
- package/source/components/popover/index.ts +4 -0
- package/source/components/popover/passport.json +238 -0
- package/source/components/popover/react/Popover.tsx +202 -0
- package/source/components/popover/react/locale.ts +5 -0
- package/source/components/popover/react/props.ts +4 -0
- package/source/components/popover/styles.css +148 -0
- package/source/components/progress/README.md +38 -0
- package/source/components/progress/core/index.ts +2 -0
- package/source/components/progress/core/progress.ts +40 -0
- package/source/components/progress/core/types.ts +23 -0
- package/source/components/progress/index.ts +7 -0
- package/source/components/progress/passport.json +270 -0
- package/source/components/progress/react/CircularProgress.tsx +106 -0
- package/source/components/progress/react/Progress.tsx +113 -0
- package/source/components/progress/react/locale.ts +7 -0
- package/source/components/progress/react/props.ts +6 -0
- package/source/components/progress/styles.css +200 -0
- package/source/components/radio-group/README.md +58 -0
- package/source/components/radio-group/core/group.ts +36 -0
- package/source/components/radio-group/core/index.ts +2 -0
- package/source/components/radio-group/core/types.ts +20 -0
- package/source/components/radio-group/index.ts +9 -0
- package/source/components/radio-group/passport.json +477 -0
- package/source/components/radio-group/react/Radio.tsx +144 -0
- package/source/components/radio-group/react/RadioGroup.tsx +179 -0
- package/source/components/radio-group/react/context.ts +18 -0
- package/source/components/radio-group/react/locale.ts +5 -0
- package/source/components/radio-group/react/props.ts +12 -0
- package/source/components/radio-group/styles.css +269 -0
- package/source/components/shared/README.md +54 -0
- package/source/components/shared/core/agent/adapter.ts +65 -0
- package/source/components/shared/core/agent/history.ts +120 -0
- package/source/components/shared/core/agent/index.ts +46 -0
- package/source/components/shared/core/agent/numbers.ts +217 -0
- package/source/components/shared/core/agent/schema.ts +180 -0
- package/source/components/shared/core/agent/types.ts +169 -0
- package/source/components/shared/core/agent/webmcp.ts +328 -0
- package/source/components/shared/core/cx.ts +9 -0
- package/source/components/shared/core/field.ts +35 -0
- package/source/components/shared/core/position.ts +124 -0
- package/source/components/shared/core/text.ts +14 -0
- package/source/components/shared/index.ts +17 -0
- package/source/components/shared/react/GramproAIProvider.tsx +50 -0
- package/source/components/shared/react/Popover.tsx +189 -0
- package/source/components/shared/react/icons.tsx +74 -0
- package/source/components/shared/react/useAskAgent.ts +217 -0
- package/source/components/shared/react/useControllableState.ts +42 -0
- package/source/components/shared/styles.css +79 -0
- package/source/components/shared/version.json +4 -0
- package/source/components/shared/version.ts +6 -0
- package/source/components/skeleton/README.md +58 -0
- package/source/components/skeleton/core/index.ts +3 -0
- package/source/components/skeleton/core/lines.ts +25 -0
- package/source/components/skeleton/core/types.ts +5 -0
- package/source/components/skeleton/index.ts +5 -0
- package/source/components/skeleton/passport.json +251 -0
- package/source/components/skeleton/react/Empty.tsx +51 -0
- package/source/components/skeleton/react/Skeleton.tsx +92 -0
- package/source/components/skeleton/react/props.ts +4 -0
- package/source/components/skeleton/styles.css +185 -0
- package/source/components/spinner/README.md +29 -0
- package/source/components/spinner/core/index.ts +3 -0
- package/source/components/spinner/core/types.ts +28 -0
- package/source/components/spinner/core/visibility.ts +34 -0
- package/source/components/spinner/index.ts +6 -0
- package/source/components/spinner/passport.json +245 -0
- package/source/components/spinner/react/Spinner.tsx +96 -0
- package/source/components/spinner/react/locale.ts +5 -0
- package/source/components/spinner/react/props.ts +4 -0
- package/source/components/spinner/react/useDelayedLoading.ts +39 -0
- package/source/components/spinner/styles.css +173 -0
- package/source/components/switch/README.md +46 -0
- package/source/components/switch/core/index.ts +2 -0
- package/source/components/switch/core/toggle.ts +54 -0
- package/source/components/switch/core/types.ts +9 -0
- package/source/components/switch/index.ts +5 -0
- package/source/components/switch/passport.json +421 -0
- package/source/components/switch/react/Switch.tsx +219 -0
- package/source/components/switch/react/locale.ts +5 -0
- package/source/components/switch/react/props.ts +12 -0
- package/source/components/switch/styles.css +227 -0
- package/source/components/tabs/README.md +32 -0
- package/source/components/tabs/core/index.ts +3 -0
- package/source/components/tabs/core/navigation.ts +54 -0
- package/source/components/tabs/core/types.ts +16 -0
- package/source/components/tabs/index.ts +5 -0
- package/source/components/tabs/passport.json +315 -0
- package/source/components/tabs/react/Tabs.tsx +306 -0
- package/source/components/tabs/react/context.ts +21 -0
- package/source/components/tabs/styles.css +263 -0
- package/source/components/textarea/README.md +39 -0
- package/source/components/textarea/core/count.ts +5 -0
- package/source/components/textarea/core/index.ts +4 -0
- package/source/components/textarea/core/size.ts +23 -0
- package/source/components/textarea/core/types.ts +17 -0
- package/source/components/textarea/index.ts +5 -0
- package/source/components/textarea/passport.json +382 -0
- package/source/components/textarea/react/Textarea.tsx +208 -0
- package/source/components/textarea/react/locale.ts +5 -0
- package/source/components/textarea/react/props.ts +4 -0
- package/source/components/textarea/styles.css +158 -0
- package/source/components/toaster/README.md +128 -0
- package/source/components/toaster/core/api.ts +87 -0
- package/source/components/toaster/core/index.ts +14 -0
- package/source/components/toaster/core/store.ts +211 -0
- package/source/components/toaster/core/toast.ts +12 -0
- package/source/components/toaster/core/types.ts +78 -0
- package/source/components/toaster/index.ts +6 -0
- package/source/components/toaster/passport.json +221 -0
- package/source/components/toaster/react/ToastItem.tsx +164 -0
- package/source/components/toaster/react/Toaster.tsx +187 -0
- package/source/components/toaster/react/icons.tsx +23 -0
- package/source/components/toaster/react/locale.ts +6 -0
- package/source/components/toaster/react/props.ts +15 -0
- package/source/components/toaster/react/useToasts.ts +11 -0
- package/source/components/toaster/styles.css +282 -0
- package/source/components/tooltip/README.md +43 -0
- package/source/components/tooltip/core/index.ts +4 -0
- package/source/components/tooltip/core/types.ts +4 -0
- package/source/components/tooltip/core/visibility.ts +34 -0
- package/source/components/tooltip/index.ts +3 -0
- package/source/components/tooltip/passport.json +170 -0
- package/source/components/tooltip/react/Tooltip.tsx +196 -0
- package/source/components/tooltip/react/props.ts +4 -0
- package/source/components/tooltip/styles.css +71 -0
- package/source/fallback/index.tsx +11 -0
- package/source/globalStyle.ts +74 -0
- package/source/hooks/SelectionHooks/type.ts +4 -0
- package/source/hooks/SelectionHooks/useClickOutside.ts +22 -0
- package/source/hooks/SelectionHooks/useMultiSelectState.ts +64 -0
- package/source/hooks/SelectionHooks/useSelectData.ts +58 -0
- package/source/hooks/SelectionHooks/useSelectState.ts +36 -0
- package/source/icon/Icon.tsx +102 -0
- package/source/icon/iconPaths.ts +206 -0
- package/source/legacy-components/bargraph/index.tsx +95 -0
- package/source/legacy-components/bargraph/type.ts +12 -0
- package/source/legacy-components/breadcrumb/index.tsx +66 -0
- package/source/legacy-components/breadcrumb/types.ts +10 -0
- package/source/legacy-components/button/index.tsx +42 -0
- package/source/legacy-components/card/index.tsx +31 -0
- package/source/legacy-components/checkbox/index.tsx +25 -0
- package/source/legacy-components/contextmenu/ContextMenu.tsx +87 -0
- package/source/legacy-components/contextmenu/ContextMenuItem.tsx +30 -0
- package/source/legacy-components/contextmenu/index.ts +2 -0
- package/source/legacy-components/contextmenu/types.ts +19 -0
- package/source/legacy-components/darkmode/index.tsx +55 -0
- package/source/legacy-components/datagrid/context/GridContext.tsx +215 -0
- package/source/legacy-components/datagrid/createTemplate.tsx +82 -0
- package/source/legacy-components/datagrid/hooks/index.ts +6 -0
- package/source/legacy-components/datagrid/hooks/useColumns.ts +33 -0
- package/source/legacy-components/datagrid/hooks/useDataSource.ts +54 -0
- package/source/legacy-components/datagrid/hooks/useFiltering.ts +169 -0
- package/source/legacy-components/datagrid/hooks/usePagination.ts +112 -0
- package/source/legacy-components/datagrid/hooks/useRowSelection.ts +48 -0
- package/source/legacy-components/datagrid/hooks/useSearch.ts +90 -0
- package/source/legacy-components/datagrid/index.tsx +28 -0
- package/source/legacy-components/datagrid/layout/FilterPopup.tsx +92 -0
- package/source/legacy-components/datagrid/layout/GridBody.tsx +184 -0
- package/source/legacy-components/datagrid/layout/GridPagination.tsx +119 -0
- package/source/legacy-components/datagrid/layout/GridToolbar.tsx +109 -0
- package/source/legacy-components/datagrid/layout/index.tsx +68 -0
- package/source/legacy-components/datagrid/type.ts +198 -0
- package/source/legacy-components/datepicker/index.tsx +365 -0
- package/source/legacy-components/datepicker/types.ts +12 -0
- package/source/legacy-components/dialog/index.tsx +44 -0
- package/source/legacy-components/dialog/types.ts +12 -0
- package/source/legacy-components/formrenderer/componentHandles/CheckBoxHandles.tsx +80 -0
- package/source/legacy-components/formrenderer/componentHandles/DatePickerHandles.tsx +93 -0
- package/source/legacy-components/formrenderer/componentHandles/InputHandles.tsx +106 -0
- package/source/legacy-components/formrenderer/componentHandles/MultiHandles.tsx +93 -0
- package/source/legacy-components/formrenderer/componentHandles/SelectHandles.tsx +95 -0
- package/source/legacy-components/formrenderer/helperFunctions.ts +72 -0
- package/source/legacy-components/formrenderer/index.tsx +93 -0
- package/source/legacy-components/formrenderer/types.ts +127 -0
- package/source/legacy-components/input/index.tsx +142 -0
- package/source/legacy-components/input/types.ts +10 -0
- package/source/legacy-components/materialInput/index.tsx +138 -0
- package/source/legacy-components/materialInput/types.ts +16 -0
- package/source/legacy-components/modal/index.tsx +152 -0
- package/source/legacy-components/modal/types.ts +19 -0
- package/source/legacy-components/multiselect/PortalDropDown.tsx +44 -0
- package/source/legacy-components/multiselect/index.tsx +269 -0
- package/source/legacy-components/multiselect/types.ts +26 -0
- package/source/legacy-components/navbar/AuthSection.tsx +98 -0
- package/source/legacy-components/navbar/MobileToggle.tsx +31 -0
- package/source/legacy-components/navbar/NavItemComponent.tsx +119 -0
- package/source/legacy-components/navbar/SearchBar.tsx +55 -0
- package/source/legacy-components/navbar/helperFunctions.ts +27 -0
- package/source/legacy-components/navbar/index.tsx +156 -0
- package/source/legacy-components/navbar/types.ts +69 -0
- package/source/legacy-components/select/PortalDropDown.tsx +59 -0
- package/source/legacy-components/select/index.tsx +249 -0
- package/source/legacy-components/select/types.ts +29 -0
- package/source/legacy-components/sidebar/components/MenuItem.tsx +101 -0
- package/source/legacy-components/sidebar/components/MenuSection.tsx +34 -0
- package/source/legacy-components/sidebar/components/SidebarFooter.tsx +50 -0
- package/source/legacy-components/sidebar/components/SidebarLogo.tsx +24 -0
- package/source/legacy-components/sidebar/components/SidebarMenu.tsx +29 -0
- package/source/legacy-components/sidebar/components/UserProfile.tsx +31 -0
- package/source/legacy-components/sidebar/hooks/useSidebarState.ts +41 -0
- package/source/legacy-components/sidebar/index.tsx +77 -0
- package/source/legacy-components/sidebar/type.ts +42 -0
- package/source/legacy-components/spinner/Stroke.tsx +89 -0
- package/source/legacy-components/spinner/index.tsx +54 -0
- package/source/legacy-components/spinner/types.ts +9 -0
- package/source/legacy-components/tabs/index.tsx +71 -0
- package/source/legacy-components/tabs/types.ts +16 -0
- package/source/legacy-components/textarea/index.tsx +123 -0
- package/source/legacy-components/textarea/types.ts +15 -0
- package/source/legacy-components/toast/ToastComponent.tsx +101 -0
- package/source/legacy-components/toast/ToastIcon.tsx +61 -0
- package/source/legacy-components/toast/index.tsx +42 -0
- package/source/legacy-components/toast/toastStore.ts +42 -0
- package/source/legacy-components/toast/types.ts +18 -0
- package/source/legacy-components/toast/useToast.ts +12 -0
- package/source/legacy-components/uploader/ProgressAnimation.tsx +50 -0
- package/source/legacy-components/uploader/UploadedFilePreview.tsx +130 -0
- package/source/legacy-components/uploader/index.tsx +311 -0
- package/source/legacy-components/uploader/types.ts +30 -0
- package/source/legacy-components/uploader/uploaderIcon.tsx +72 -0
- package/source/legacy-components/uploader/uploaderService.ts +134 -0
- package/source/legacy-components/useUploader/useUploader.tsx +310 -0
- package/source/legacy-components/usepaginateddata/usePaginatedData.ts +174 -0
- package/source/theme.ts +40 -0
- package/source/utils.ts +10 -0
- package/tools/env.cjs +61 -0
- package/tools/passport/cli.cjs +79 -0
- package/tools/passport/extract.cjs +493 -0
- package/tools/passport/index.cjs +185 -0
- package/tools/passport/merge.cjs +131 -0
- package/tools/passport/policy.cjs +65 -0
- package/tools/passport/validate.cjs +277 -0
- package/tools/ts-require.cjs +79 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
use,
|
|
5
|
+
useId,
|
|
6
|
+
useImperativeHandle,
|
|
7
|
+
useRef,
|
|
8
|
+
type ChangeEvent,
|
|
9
|
+
type ChangeEventHandler,
|
|
10
|
+
type InputHTMLAttributes,
|
|
11
|
+
type ReactNode,
|
|
12
|
+
type Ref,
|
|
13
|
+
} from "react";
|
|
14
|
+
import { useControllableState } from "../../shared/react/useControllableState";
|
|
15
|
+
import { describeField } from "../../shared/core/field";
|
|
16
|
+
import type { RadioSize } from "../core/types";
|
|
17
|
+
import { RadioGroupContext } from "./context";
|
|
18
|
+
import { cx, type RadioSlot } from "./props";
|
|
19
|
+
|
|
20
|
+
export interface RadioProps
|
|
21
|
+
extends Omit<
|
|
22
|
+
InputHTMLAttributes<HTMLInputElement>,
|
|
23
|
+
"type" | "size" | "checked" | "defaultChecked" | "onChange"
|
|
24
|
+
> {
|
|
25
|
+
/** The value this choice contributes to its group. */
|
|
26
|
+
value: string;
|
|
27
|
+
/** Selected (controlled). Inside a RadioGroup the group decides instead. */
|
|
28
|
+
checked?: boolean;
|
|
29
|
+
defaultChecked?: boolean;
|
|
30
|
+
onCheckedChange?(checked: boolean): void;
|
|
31
|
+
onChange?: ChangeEventHandler<HTMLInputElement>;
|
|
32
|
+
label?: ReactNode;
|
|
33
|
+
description?: ReactNode;
|
|
34
|
+
error?: ReactNode;
|
|
35
|
+
size?: RadioSize;
|
|
36
|
+
classNames?: Partial<Record<RadioSlot, string>>;
|
|
37
|
+
/** The `<input>` element. */
|
|
38
|
+
ref?: Ref<HTMLInputElement>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* One choice, as a native radio. Inside a `RadioGroup` the group owns the
|
|
43
|
+
* value; on its own it behaves like any other radio sharing a `name`.
|
|
44
|
+
*
|
|
45
|
+
* Nothing here manages focus: radios that share a `name` already roam with the
|
|
46
|
+
* arrow keys, skip the disabled ones, wrap around and leave one tab stop for
|
|
47
|
+
* the whole group — in every browser, and without JavaScript.
|
|
48
|
+
*/
|
|
49
|
+
export function Radio(props: RadioProps) {
|
|
50
|
+
const {
|
|
51
|
+
ref,
|
|
52
|
+
value,
|
|
53
|
+
checked: checkedProp,
|
|
54
|
+
defaultChecked = false,
|
|
55
|
+
onCheckedChange,
|
|
56
|
+
onChange,
|
|
57
|
+
label,
|
|
58
|
+
description,
|
|
59
|
+
error,
|
|
60
|
+
size,
|
|
61
|
+
className,
|
|
62
|
+
classNames,
|
|
63
|
+
style,
|
|
64
|
+
id: idProp,
|
|
65
|
+
disabled,
|
|
66
|
+
required,
|
|
67
|
+
name,
|
|
68
|
+
"aria-describedby": describedByProp,
|
|
69
|
+
...inputProps
|
|
70
|
+
} = props;
|
|
71
|
+
|
|
72
|
+
const group = use(RadioGroupContext);
|
|
73
|
+
const reactId = useId();
|
|
74
|
+
const id = idProp ?? reactId;
|
|
75
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
76
|
+
useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);
|
|
77
|
+
|
|
78
|
+
const [own, setOwn] = useControllableState(checkedProp, defaultChecked);
|
|
79
|
+
const checked = group !== null ? group.value === value : own;
|
|
80
|
+
|
|
81
|
+
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
|
82
|
+
if (group !== null) group.select(value);
|
|
83
|
+
else setOwn(event.target.checked);
|
|
84
|
+
onChange?.(event);
|
|
85
|
+
onCheckedChange?.(event.target.checked);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const isDisabled = disabled ?? group?.disabled;
|
|
89
|
+
const invalid = Boolean(error) || (group?.invalid ?? false);
|
|
90
|
+
const describedBy = describeField(id, { extra: describedByProp, description, error });
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
className={cx("rd-root", classNames?.root, className)}
|
|
95
|
+
style={style}
|
|
96
|
+
data-size={size ?? group?.size ?? "md"}
|
|
97
|
+
data-variant={group?.variant ?? "default"}
|
|
98
|
+
data-checked={checked || undefined}
|
|
99
|
+
data-disabled={isDisabled || undefined}
|
|
100
|
+
data-invalid={invalid ? "" : undefined}
|
|
101
|
+
>
|
|
102
|
+
<span className={cx("rd-control", classNames?.control)}>
|
|
103
|
+
<input
|
|
104
|
+
{...inputProps}
|
|
105
|
+
ref={inputRef}
|
|
106
|
+
id={id}
|
|
107
|
+
type="radio"
|
|
108
|
+
className={cx("rd-input", classNames?.input)}
|
|
109
|
+
checked={checked}
|
|
110
|
+
value={value}
|
|
111
|
+
name={name ?? group?.name}
|
|
112
|
+
disabled={isDisabled}
|
|
113
|
+
// Every radio in a group carries `required`, which is how a browser
|
|
114
|
+
// validates the group as a whole rather than one button in it.
|
|
115
|
+
required={required ?? group?.required}
|
|
116
|
+
aria-invalid={invalid || undefined}
|
|
117
|
+
aria-describedby={describedBy}
|
|
118
|
+
onChange={handleChange}
|
|
119
|
+
/>
|
|
120
|
+
<span className="rd-dot" aria-hidden="true" />
|
|
121
|
+
</span>
|
|
122
|
+
|
|
123
|
+
{(label || description || error) && (
|
|
124
|
+
<span className="rd-text">
|
|
125
|
+
{label && (
|
|
126
|
+
<label htmlFor={id} className={cx("rd-label", classNames?.label)}>
|
|
127
|
+
{label}
|
|
128
|
+
</label>
|
|
129
|
+
)}
|
|
130
|
+
{description && (
|
|
131
|
+
<span id={`${id}-description`} className={cx("rd-description", classNames?.description)}>
|
|
132
|
+
{description}
|
|
133
|
+
</span>
|
|
134
|
+
)}
|
|
135
|
+
{error && (
|
|
136
|
+
<span id={`${id}-error`} className={cx("rd-error", classNames?.error)} role="alert">
|
|
137
|
+
{error}
|
|
138
|
+
</span>
|
|
139
|
+
)}
|
|
140
|
+
</span>
|
|
141
|
+
)}
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useId, useMemo, type CSSProperties, type ReactNode } from "react";
|
|
4
|
+
import { useControllableState } from "../../shared/react/useControllableState";
|
|
5
|
+
import { describeField } from "../../shared/core/field";
|
|
6
|
+
import { hasEnabledOption, normalizeOptions, resolveValue } from "../core/group";
|
|
7
|
+
import type {
|
|
8
|
+
RadioGroupLocaleText,
|
|
9
|
+
RadioOption,
|
|
10
|
+
RadioOrientation,
|
|
11
|
+
RadioSize,
|
|
12
|
+
RadioVariant,
|
|
13
|
+
} from "../core/types";
|
|
14
|
+
import { Radio } from "./Radio";
|
|
15
|
+
import { RadioGroupContext, type RadioGroupContextValue } from "./context";
|
|
16
|
+
import { defaultRadioGroupText } from "./locale";
|
|
17
|
+
import { cx, type RadioGroupSlot } from "./props";
|
|
18
|
+
|
|
19
|
+
export interface RadioGroupProps {
|
|
20
|
+
/** The chosen value (controlled). `null` for nothing chosen. */
|
|
21
|
+
value?: string | null;
|
|
22
|
+
defaultValue?: string | null;
|
|
23
|
+
onValueChange?(value: string | null): void;
|
|
24
|
+
/** Render these choices, or pass `<Radio value="…">` children. Plain strings work too. */
|
|
25
|
+
options?: readonly (string | RadioOption)[];
|
|
26
|
+
children?: ReactNode;
|
|
27
|
+
/** The question the choices answer, shown as the group's legend. */
|
|
28
|
+
label?: ReactNode;
|
|
29
|
+
description?: ReactNode;
|
|
30
|
+
error?: ReactNode;
|
|
31
|
+
required?: boolean;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/** Form field name shared by every radio. One is generated when it is left out. */
|
|
34
|
+
name?: string;
|
|
35
|
+
size?: RadioSize;
|
|
36
|
+
/** Default `vertical`. */
|
|
37
|
+
orientation?: RadioOrientation;
|
|
38
|
+
/** Default `default`. `card` draws each choice as a tile. */
|
|
39
|
+
variant?: RadioVariant;
|
|
40
|
+
/**
|
|
41
|
+
* Offer a button that empties the group. Radios cannot be unselected by
|
|
42
|
+
* clicking or by keyboard — that is the control's nature, not an oversight —
|
|
43
|
+
* so an optional choice needs either this or a "None" option of its own.
|
|
44
|
+
*/
|
|
45
|
+
clearable?: boolean;
|
|
46
|
+
id?: string;
|
|
47
|
+
className?: string;
|
|
48
|
+
classNames?: Partial<Record<RadioGroupSlot, string>>;
|
|
49
|
+
style?: CSSProperties;
|
|
50
|
+
localeText?: Partial<RadioGroupLocaleText>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A labelled set of radios sharing one value. */
|
|
54
|
+
export function RadioGroup(props: RadioGroupProps) {
|
|
55
|
+
const {
|
|
56
|
+
value,
|
|
57
|
+
defaultValue,
|
|
58
|
+
onValueChange,
|
|
59
|
+
options,
|
|
60
|
+
children,
|
|
61
|
+
label,
|
|
62
|
+
description,
|
|
63
|
+
error,
|
|
64
|
+
required = false,
|
|
65
|
+
disabled = false,
|
|
66
|
+
name: nameProp,
|
|
67
|
+
size,
|
|
68
|
+
orientation = "vertical",
|
|
69
|
+
variant = "default",
|
|
70
|
+
clearable = false,
|
|
71
|
+
id: idProp,
|
|
72
|
+
className,
|
|
73
|
+
classNames,
|
|
74
|
+
style,
|
|
75
|
+
localeText,
|
|
76
|
+
} = props;
|
|
77
|
+
|
|
78
|
+
const reactId = useId();
|
|
79
|
+
const id = idProp ?? reactId;
|
|
80
|
+
// Radios are grouped by their name, so one is needed whether or not the
|
|
81
|
+
// group posts with a form: without it, two groups on a page share arrows.
|
|
82
|
+
const name = nameProp ?? `${id}-radio`;
|
|
83
|
+
const text = useMemo(() => ({ ...defaultRadioGroupText, ...localeText }), [localeText]);
|
|
84
|
+
const [current, setCurrent] = useControllableState<string | null>(value, defaultValue ?? null);
|
|
85
|
+
|
|
86
|
+
const items = useMemo(() => (options ? normalizeOptions(options) : null), [options]);
|
|
87
|
+
// With children rather than options there is nothing to check the value
|
|
88
|
+
// against, so it is taken as given.
|
|
89
|
+
const selected = items ? resolveValue(items, current) : (current ?? null);
|
|
90
|
+
|
|
91
|
+
const commit = useCallback(
|
|
92
|
+
(next: string | null) => {
|
|
93
|
+
setCurrent(next);
|
|
94
|
+
onValueChange?.(next);
|
|
95
|
+
},
|
|
96
|
+
[setCurrent, onValueChange],
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const context = useMemo<RadioGroupContextValue>(
|
|
100
|
+
() => ({
|
|
101
|
+
value: selected,
|
|
102
|
+
select: commit,
|
|
103
|
+
name,
|
|
104
|
+
disabled,
|
|
105
|
+
required,
|
|
106
|
+
invalid: Boolean(error),
|
|
107
|
+
size,
|
|
108
|
+
variant,
|
|
109
|
+
}),
|
|
110
|
+
[selected, commit, name, disabled, required, error, size, variant],
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const showClear = clearable && selected !== null && hasEnabledOption(items ?? [], disabled);
|
|
114
|
+
const describedBy = describeField(id, { description, error });
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<fieldset
|
|
118
|
+
id={id}
|
|
119
|
+
className={cx("rd-group", classNames?.root, className)}
|
|
120
|
+
style={style}
|
|
121
|
+
// A disabled fieldset disables every control inside it natively.
|
|
122
|
+
disabled={disabled}
|
|
123
|
+
// A fieldset is a plain group by default, which is right for checkboxes
|
|
124
|
+
// and wrong here: a set of radios is one control with one value, and
|
|
125
|
+
// screen readers say so and count the choices ("2 of 3") only for
|
|
126
|
+
// radiogroup. The legend is repeated as the name, because overriding the
|
|
127
|
+
// role is not guaranteed to carry a fieldset's own naming with it.
|
|
128
|
+
role="radiogroup"
|
|
129
|
+
aria-labelledby={label ? `${id}-legend` : undefined}
|
|
130
|
+
aria-describedby={describedBy}
|
|
131
|
+
data-orientation={orientation}
|
|
132
|
+
data-variant={variant}
|
|
133
|
+
data-invalid={error ? "" : undefined}
|
|
134
|
+
>
|
|
135
|
+
{label && (
|
|
136
|
+
<legend id={`${id}-legend`} className={cx("rd-legend", classNames?.legend)} data-required={required || undefined}>
|
|
137
|
+
{label}
|
|
138
|
+
</legend>
|
|
139
|
+
)}
|
|
140
|
+
{description && (
|
|
141
|
+
<span id={`${id}-description`} className={cx("rd-description", classNames?.description)}>
|
|
142
|
+
{description}
|
|
143
|
+
</span>
|
|
144
|
+
)}
|
|
145
|
+
|
|
146
|
+
<RadioGroupContext value={context}>
|
|
147
|
+
<div className={cx("rd-items", classNames?.items)}>
|
|
148
|
+
{items
|
|
149
|
+
? items.map((option) => (
|
|
150
|
+
<Radio
|
|
151
|
+
key={option.value}
|
|
152
|
+
value={option.value}
|
|
153
|
+
label={option.label}
|
|
154
|
+
description={option.description}
|
|
155
|
+
disabled={option.disabled}
|
|
156
|
+
/>
|
|
157
|
+
))
|
|
158
|
+
: children}
|
|
159
|
+
</div>
|
|
160
|
+
</RadioGroupContext>
|
|
161
|
+
|
|
162
|
+
{showClear && (
|
|
163
|
+
<button
|
|
164
|
+
type="button"
|
|
165
|
+
className={cx("rd-clear", classNames?.clear)}
|
|
166
|
+
onClick={() => commit(null)}
|
|
167
|
+
>
|
|
168
|
+
{text.clear}
|
|
169
|
+
</button>
|
|
170
|
+
)}
|
|
171
|
+
|
|
172
|
+
{error && (
|
|
173
|
+
<span id={`${id}-error`} className={cx("rd-error", classNames?.error)} role="alert">
|
|
174
|
+
{error}
|
|
175
|
+
</span>
|
|
176
|
+
)}
|
|
177
|
+
</fieldset>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext } from "react";
|
|
4
|
+
import type { RadioSize, RadioVariant } from "../core/types";
|
|
5
|
+
|
|
6
|
+
export interface RadioGroupContextValue {
|
|
7
|
+
value: string | null;
|
|
8
|
+
select(value: string): void;
|
|
9
|
+
name: string;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
required: boolean;
|
|
12
|
+
invalid: boolean;
|
|
13
|
+
size?: RadioSize;
|
|
14
|
+
variant: RadioVariant;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Lets each Radio inside a RadioGroup read the group's value and change it. */
|
|
18
|
+
export const RadioGroupContext = createContext<RadioGroupContextValue | null>(null);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type RadioSlot =
|
|
2
|
+
| "root"
|
|
3
|
+
| "control"
|
|
4
|
+
| "input"
|
|
5
|
+
| "label"
|
|
6
|
+
| "description"
|
|
7
|
+
| "error";
|
|
8
|
+
|
|
9
|
+
export type RadioGroupSlot = "root" | "legend" | "description" | "items" | "clear" | "error";
|
|
10
|
+
|
|
11
|
+
// Shared with every other component, so class handling cannot drift.
|
|
12
|
+
export { cx } from "../../shared/core/cx";
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Radio and RadioGroup styles.
|
|
3
|
+
*
|
|
4
|
+
* The button is the native <input type="radio"> with `appearance: none`, so it
|
|
5
|
+
* keeps native behavior: arrow keys roam the group, one tab stop, and the
|
|
6
|
+
* whole group validates as one required field. Tokens read the shared --gbs-*
|
|
7
|
+
* variables when they are set on an ancestor (set them on :root to theme every
|
|
8
|
+
* component at once). Rules are unlayered: they beat a framework reset on
|
|
9
|
+
* specificity, and lose to anything you pass through `className`. With
|
|
10
|
+
* Tailwind v4, import this file after the framework and inside its components
|
|
11
|
+
* layer - see the README.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
.rd-root,
|
|
15
|
+
.rd-group {
|
|
16
|
+
--rd-fg: var(--gbs-fg, var(--dg-fg, light-dark(#18181b, #f4f4f5)));
|
|
17
|
+
--rd-muted: var(--gbs-muted, var(--dg-muted, light-dark(#71717a, #a1a1aa)));
|
|
18
|
+
--rd-border: var(--gbs-border-control, light-dark(#a1a1aa, #52525b));
|
|
19
|
+
--rd-card-border: var(--gbs-border, var(--dg-border, light-dark(#e4e4e7, #27272a)));
|
|
20
|
+
--rd-input-bg: var(--gbs-input-bg, var(--dg-input-bg, light-dark(#ffffff, #121216)));
|
|
21
|
+
--rd-hover: var(--gbs-hover, var(--dg-hover, light-dark(#f4f4f5, #1f1f23)));
|
|
22
|
+
--rd-accent: var(--gbs-accent, var(--dg-accent, light-dark(#2563eb, #60a5fa)));
|
|
23
|
+
--rd-accent-soft: var(--gbs-accent-soft, var(--dg-accent-soft, light-dark(#eff6ff, #172554)));
|
|
24
|
+
--rd-focus: var(--gbs-focus, var(--dg-focus, light-dark(#2563eb, #60a5fa)));
|
|
25
|
+
--rd-danger: var(--gbs-danger, var(--dg-danger, light-dark(#dc2626, #f87171)));
|
|
26
|
+
--rd-radius: var(--gbs-radius, var(--dg-radius, 8px));
|
|
27
|
+
--rd-font-size: var(--gbs-font-size, var(--dg-font-size, 13px));
|
|
28
|
+
--rd-size: 16px;
|
|
29
|
+
|
|
30
|
+
color-scheme: inherit;
|
|
31
|
+
font-size: var(--rd-font-size);
|
|
32
|
+
line-height: 1.4;
|
|
33
|
+
color: var(--rd-fg);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:where(.dark, [data-theme="dark"]) :is(.rd-root, .rd-group) {
|
|
37
|
+
color-scheme: dark;
|
|
38
|
+
}
|
|
39
|
+
:where(.light, [data-theme="light"]) :is(.rd-root, .rd-group) {
|
|
40
|
+
color-scheme: light;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:where(.rd-root, .rd-group) *,
|
|
44
|
+
:where(.rd-root, .rd-group) *::before,
|
|
45
|
+
:where(.rd-root, .rd-group) *::after {
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* ---------------------------------------------------------------- radio */
|
|
50
|
+
|
|
51
|
+
.rd-root {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: flex-start;
|
|
54
|
+
gap: 8px;
|
|
55
|
+
min-width: 0;
|
|
56
|
+
}
|
|
57
|
+
.rd-root[data-size="sm"] {
|
|
58
|
+
--rd-size: 14px;
|
|
59
|
+
--rd-font-size: 12px;
|
|
60
|
+
}
|
|
61
|
+
.rd-root[data-size="lg"] {
|
|
62
|
+
--rd-size: 20px;
|
|
63
|
+
--rd-font-size: 14px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.rd-control {
|
|
67
|
+
position: relative;
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
flex: none;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
/* Line the button up with the first line of the label. */
|
|
73
|
+
height: calc(var(--rd-font-size) * 1.4);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.rd-input {
|
|
77
|
+
width: var(--rd-size);
|
|
78
|
+
height: var(--rd-size);
|
|
79
|
+
margin: 0;
|
|
80
|
+
border: 1px solid var(--rd-border);
|
|
81
|
+
border-radius: 50%;
|
|
82
|
+
appearance: none;
|
|
83
|
+
background: var(--rd-input-bg);
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
transition:
|
|
86
|
+
border-color 120ms ease,
|
|
87
|
+
background-color 120ms ease;
|
|
88
|
+
}
|
|
89
|
+
.rd-input:hover:not(:disabled) {
|
|
90
|
+
border-color: var(--rd-accent);
|
|
91
|
+
}
|
|
92
|
+
.rd-input:checked {
|
|
93
|
+
border-color: var(--rd-accent);
|
|
94
|
+
border-width: 2px;
|
|
95
|
+
}
|
|
96
|
+
.rd-input:focus-visible {
|
|
97
|
+
outline: 2px solid var(--rd-focus);
|
|
98
|
+
outline-offset: 2px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* The dot is a separate element rather than a border trick, so its size can
|
|
102
|
+
follow the control's and it can animate in. */
|
|
103
|
+
.rd-dot {
|
|
104
|
+
position: absolute;
|
|
105
|
+
width: calc(var(--rd-size) / 2);
|
|
106
|
+
height: calc(var(--rd-size) / 2);
|
|
107
|
+
border-radius: 50%;
|
|
108
|
+
background: var(--rd-accent);
|
|
109
|
+
scale: 0;
|
|
110
|
+
transition: scale 120ms ease;
|
|
111
|
+
pointer-events: none;
|
|
112
|
+
}
|
|
113
|
+
.rd-input:checked ~ .rd-dot {
|
|
114
|
+
scale: 1;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.rd-root[data-invalid] .rd-input {
|
|
118
|
+
border-color: var(--rd-danger);
|
|
119
|
+
}
|
|
120
|
+
/* Only the button dims. Fading the whole choice takes its label below the
|
|
121
|
+
contrast floor, and someone still has to be able to read the option they
|
|
122
|
+
cannot pick. */
|
|
123
|
+
.rd-input:disabled {
|
|
124
|
+
opacity: 0.5;
|
|
125
|
+
cursor: not-allowed;
|
|
126
|
+
}
|
|
127
|
+
.rd-root[data-disabled] .rd-dot {
|
|
128
|
+
opacity: 0.5;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.rd-text {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-direction: column;
|
|
134
|
+
gap: 2px;
|
|
135
|
+
min-width: 0;
|
|
136
|
+
}
|
|
137
|
+
.rd-label {
|
|
138
|
+
font-weight: 500;
|
|
139
|
+
cursor: pointer;
|
|
140
|
+
}
|
|
141
|
+
.rd-root[data-disabled] .rd-label {
|
|
142
|
+
color: var(--rd-muted);
|
|
143
|
+
cursor: not-allowed;
|
|
144
|
+
}
|
|
145
|
+
.rd-description {
|
|
146
|
+
color: var(--rd-muted);
|
|
147
|
+
text-wrap: pretty;
|
|
148
|
+
}
|
|
149
|
+
.rd-error {
|
|
150
|
+
color: var(--rd-danger);
|
|
151
|
+
text-wrap: pretty;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* ----------------------------------------------------------------- card */
|
|
155
|
+
|
|
156
|
+
.rd-root[data-variant="card"] {
|
|
157
|
+
position: relative;
|
|
158
|
+
align-items: flex-start;
|
|
159
|
+
padding: 12px;
|
|
160
|
+
border: 1px solid var(--rd-card-border);
|
|
161
|
+
border-radius: var(--rd-radius);
|
|
162
|
+
background: var(--rd-input-bg);
|
|
163
|
+
cursor: pointer;
|
|
164
|
+
transition:
|
|
165
|
+
border-color 120ms ease,
|
|
166
|
+
background-color 120ms ease;
|
|
167
|
+
}
|
|
168
|
+
.rd-root[data-variant="card"]:hover:not([data-disabled]) {
|
|
169
|
+
background: var(--rd-hover);
|
|
170
|
+
}
|
|
171
|
+
.rd-root[data-variant="card"][data-checked] {
|
|
172
|
+
border-color: var(--rd-accent);
|
|
173
|
+
background: var(--rd-accent-soft);
|
|
174
|
+
}
|
|
175
|
+
/* Muted grey clears 4.5:1 on white but only reaches 4.44:1 on the tinted
|
|
176
|
+
background of a selected card, so it moves a step towards the text colour
|
|
177
|
+
there rather than the description quietly failing contrast. */
|
|
178
|
+
.rd-root[data-variant="card"][data-checked] .rd-description {
|
|
179
|
+
color: color-mix(in oklab, var(--rd-muted) 72%, var(--rd-fg));
|
|
180
|
+
}
|
|
181
|
+
/* The whole tile is the target: the input covers it, so a press anywhere
|
|
182
|
+
lands on the radio itself rather than on a label that forwards it. */
|
|
183
|
+
.rd-root[data-variant="card"] .rd-input::after {
|
|
184
|
+
content: "";
|
|
185
|
+
position: absolute;
|
|
186
|
+
inset: 0;
|
|
187
|
+
border-radius: var(--rd-radius);
|
|
188
|
+
}
|
|
189
|
+
.rd-root[data-variant="card"]:has(.rd-input:focus-visible) {
|
|
190
|
+
outline: 2px solid var(--rd-focus);
|
|
191
|
+
outline-offset: 2px;
|
|
192
|
+
}
|
|
193
|
+
.rd-root[data-variant="card"] .rd-input:focus-visible {
|
|
194
|
+
outline: none;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* ---------------------------------------------------------------- group */
|
|
198
|
+
|
|
199
|
+
.rd-group {
|
|
200
|
+
display: flex;
|
|
201
|
+
flex-direction: column;
|
|
202
|
+
gap: 8px;
|
|
203
|
+
min-width: 0;
|
|
204
|
+
margin: 0;
|
|
205
|
+
padding: 0;
|
|
206
|
+
border: 0;
|
|
207
|
+
}
|
|
208
|
+
.rd-legend {
|
|
209
|
+
padding: 0;
|
|
210
|
+
font-weight: 500;
|
|
211
|
+
}
|
|
212
|
+
.rd-legend[data-required]::after {
|
|
213
|
+
content: " *";
|
|
214
|
+
color: var(--rd-danger);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.rd-items {
|
|
218
|
+
display: flex;
|
|
219
|
+
flex-direction: column;
|
|
220
|
+
gap: 8px;
|
|
221
|
+
min-width: 0;
|
|
222
|
+
}
|
|
223
|
+
.rd-group[data-orientation="horizontal"] .rd-items {
|
|
224
|
+
flex-flow: row wrap;
|
|
225
|
+
gap: 16px;
|
|
226
|
+
}
|
|
227
|
+
.rd-group[data-variant="card"][data-orientation="horizontal"] .rd-items {
|
|
228
|
+
gap: 8px;
|
|
229
|
+
}
|
|
230
|
+
.rd-group[data-variant="card"][data-orientation="horizontal"] .rd-root {
|
|
231
|
+
flex: 1 1 180px;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.rd-clear {
|
|
235
|
+
align-self: flex-start;
|
|
236
|
+
padding: 0;
|
|
237
|
+
border: 0;
|
|
238
|
+
background: none;
|
|
239
|
+
color: var(--rd-accent);
|
|
240
|
+
font: inherit;
|
|
241
|
+
text-decoration: underline;
|
|
242
|
+
text-underline-offset: 2px;
|
|
243
|
+
cursor: pointer;
|
|
244
|
+
}
|
|
245
|
+
.rd-clear:focus-visible {
|
|
246
|
+
outline: 2px solid var(--rd-focus);
|
|
247
|
+
outline-offset: 2px;
|
|
248
|
+
border-radius: 3px;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@media (prefers-reduced-motion: reduce) {
|
|
252
|
+
.rd-input,
|
|
253
|
+
.rd-dot,
|
|
254
|
+
.rd-root[data-variant="card"] {
|
|
255
|
+
transition: none;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@media (forced-colors: active) {
|
|
260
|
+
.rd-input {
|
|
261
|
+
border: 1px solid CanvasText;
|
|
262
|
+
}
|
|
263
|
+
.rd-dot {
|
|
264
|
+
background: Highlight;
|
|
265
|
+
}
|
|
266
|
+
.rd-root[data-variant="card"][data-checked] {
|
|
267
|
+
border-color: Highlight;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Shared
|
|
2
|
+
|
|
3
|
+
The small amount of code every component needs. It is not a component and is
|
|
4
|
+
not chosen from the installer's list: `shared/` is copied into `component-lib/`
|
|
5
|
+
with any install, and each component reaches it at exactly `../../shared/…`.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { cx } from "../../shared/core/cx";
|
|
9
|
+
import { describeField } from "../../shared/core/field";
|
|
10
|
+
import { AnchoredPopover } from "../../shared/react/Popover";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| Export | Where | What it is |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `cx(...names)` | `core/cx` | Joins class names, dropping anything falsy. |
|
|
16
|
+
| `countCharacters(value)` | `core/text` | Grapheme-accurate length for character counters. |
|
|
17
|
+
| `describeField(id, parts)` | `core/field` | The `aria-describedby` for a control, from its hint, description and error. |
|
|
18
|
+
| `useControllableState(value, default)` | `react/useControllableState` | One value that may be controlled or owned by the component. |
|
|
19
|
+
| `AnchoredPopover` | `react/Popover` | Anchored popover on the native Popover API: top layer, light dismiss, flipping. |
|
|
20
|
+
| `Svg` and the shared glyphs | `react/icons` | The icon base, plus every glyph more than one component draws. |
|
|
21
|
+
|
|
22
|
+
`core/` is framework-free and `react/` is `"use client"`, the same split every
|
|
23
|
+
component uses.
|
|
24
|
+
|
|
25
|
+
## The rules
|
|
26
|
+
|
|
27
|
+
**Only `shared/` is shared.** A component never imports another component: each
|
|
28
|
+
is copied into a project on its own, so a sibling it reached for might not be
|
|
29
|
+
there. `__tests__/boundaries.test.ts` enforces this, along with the ban on
|
|
30
|
+
third-party imports.
|
|
31
|
+
|
|
32
|
+
**`shared/` never imports a component.** It has to stand on its own, and a
|
|
33
|
+
back-edge would make the folder uninstallable without the component it points
|
|
34
|
+
at.
|
|
35
|
+
|
|
36
|
+
**Changes here are additive.** Installing a component overwrites `shared/` with
|
|
37
|
+
the version that component was built against, and the other components already
|
|
38
|
+
in the project keep running against it. So add exports, add optional parameters,
|
|
39
|
+
and leave existing signatures alone; if something genuinely has to change shape,
|
|
40
|
+
ship it under a new name. `version.ts` and `version.json` are bumped together on
|
|
41
|
+
every change, and the installer compares them to refuse a downgrade.
|
|
42
|
+
|
|
43
|
+
**Nothing component-specific.** A hook only one component uses belongs in that
|
|
44
|
+
component, where it can change freely. This folder is for what is provably
|
|
45
|
+
duplicated: a shape drawn by two components, a rule two controls must agree on.
|
|
46
|
+
|
|
47
|
+
## What deliberately stays out
|
|
48
|
+
|
|
49
|
+
`useCombobox`, `useDatePicker` and the grid's state live with their components:
|
|
50
|
+
they are the component, not a primitive. The grid also keeps its own controlled
|
|
51
|
+
state, because it is one object of nine independent slices rather than a single
|
|
52
|
+
value, and `useControllableState` would obscure more than it saved. A component
|
|
53
|
+
inside a `CheckboxGroup` defers to the group instead, and only falls back to
|
|
54
|
+
`useControllableState` when it stands alone.
|