@hina-ui/vue 1.7.4 → 1.7.6
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/README.md +37 -0
- package/dist/index.js +2251 -992
- package/dist/index.js.map +1 -1
- package/dist/shared/behavior/anchor-follow.ts +95 -0
- package/dist/shared/behavior/form.ts +187 -0
- package/dist/shared/behavior/ripple.ts +222 -0
- package/dist/shared/behavior/spoiler/painter.ts +197 -0
- package/dist/shared/behavior/spoiler/worklet.ts +199 -0
- package/dist/shared/behavior/toast.ts +243 -0
- package/dist/shared/lib/anchor.ts +83 -0
- package/dist/shared/lib/banner.ts +10 -0
- package/dist/shared/lib/calendar/format.ts +23 -0
- package/dist/shared/lib/caret.ts +48 -0
- package/dist/shared/lib/collapse.ts +29 -0
- package/dist/shared/lib/command-palette/hotkey.ts +27 -0
- package/dist/shared/lib/command-palette/match.ts +92 -0
- package/dist/shared/lib/data-list.ts +40 -0
- package/dist/shared/lib/data-table/column-sizing-styles.ts +41 -0
- package/dist/shared/lib/data-table/column-sizing.ts +101 -0
- package/dist/shared/lib/data-table/csv.ts +51 -0
- package/dist/shared/lib/data-table/layout.ts +199 -0
- package/dist/shared/lib/data-table/resize.ts +66 -0
- package/dist/shared/lib/data-table/state.ts +226 -0
- package/dist/shared/lib/data-table/utils.ts +80 -0
- package/dist/shared/lib/date-range-field/validity.ts +21 -0
- package/dist/shared/lib/date.ts +111 -0
- package/dist/shared/lib/field-focus.ts +36 -0
- package/dist/shared/lib/file-upload/select.ts +58 -0
- package/dist/shared/lib/file-upload/size.ts +16 -0
- package/dist/shared/lib/form/errors.ts +48 -0
- package/dist/shared/lib/form/focus.ts +10 -0
- package/dist/shared/lib/form/standard-schema.ts +26 -0
- package/dist/shared/lib/form/values.ts +23 -0
- package/dist/shared/lib/highlighter.ts +98 -0
- package/dist/shared/lib/iris-origin.ts +40 -0
- package/dist/shared/lib/lightbox/clip.ts +117 -0
- package/dist/shared/lib/lightbox/download.ts +29 -0
- package/dist/shared/lib/lightbox/gesture.ts +54 -0
- package/dist/shared/lib/lightbox/paging.ts +33 -0
- package/dist/shared/lib/lightbox/pose.ts +142 -0
- package/dist/shared/lib/lightbox/source.ts +17 -0
- package/dist/shared/lib/lightbox/types.ts +14 -0
- package/dist/shared/lib/lightbox/zoom.ts +127 -0
- package/dist/shared/lib/meter-group.ts +16 -0
- package/dist/shared/lib/overlay-anchor.ts +42 -0
- package/dist/shared/lib/pagination.ts +16 -0
- package/dist/shared/lib/pointer-corridor.ts +26 -0
- package/dist/shared/lib/qr-code-export.ts +68 -0
- package/dist/shared/lib/range-calendar/limit.ts +11 -0
- package/dist/shared/lib/rating.ts +4 -0
- package/dist/shared/lib/relative-time.ts +20 -0
- package/dist/shared/lib/scroll-area.ts +77 -0
- package/dist/shared/lib/scroll-restore.ts +148 -0
- package/dist/shared/lib/toast-layout.ts +42 -0
- package/dist/shared/lib/tree/selection.ts +131 -0
- package/dist/shared/lib/tree-select/filter.ts +19 -0
- package/dist/shared/lib/virtual/choices.ts +193 -0
- package/dist/shared/lib/virtual/collection.ts +71 -0
- package/dist/shared/lib/virtual/filter.ts +26 -0
- package/dist/shared/lib/virtual/flow.ts +32 -0
- package/dist/shared/lib/virtual/list.ts +63 -0
- package/dist/shared/lib/virtual/navigation.ts +26 -0
- package/dist/shared/lib/virtual/tree.ts +98 -0
- package/dist/shared/locale/en-US.ts +220 -0
- package/dist/shared/locale/index.ts +52 -0
- package/dist/shared/locale/types.ts +225 -0
- package/dist/shared/locale/zh-CN.ts +215 -0
- package/dist/shared/primitives/number-field/LICENSE +21 -0
- package/dist/shared/primitives/number-field/index.ts +407 -0
- package/dist/shared/styles/semantic.css +10 -2
- package/dist/shared/types/autocomplete.ts +16 -0
- package/dist/shared/types/data-table.ts +170 -0
- package/dist/shared/types/pagination.ts +19 -0
- package/dist/shared/types/select.ts +23 -0
- package/dist/shared/types/tree-select.ts +34 -0
- package/dist/shared/types/tree.ts +20 -0
- package/dist/types/shared/src/behavior/anchor-follow.d.ts +13 -0
- package/dist/types/shared/src/behavior/anchor-follow.d.ts.map +1 -0
- package/dist/types/shared/src/behavior/form.d.ts +24 -0
- package/dist/types/shared/src/behavior/form.d.ts.map +1 -0
- package/dist/types/shared/src/behavior/ripple.d.ts +11 -0
- package/dist/types/shared/src/behavior/ripple.d.ts.map +1 -0
- package/dist/types/shared/src/behavior/spoiler/painter.d.ts +35 -0
- package/dist/types/shared/src/behavior/spoiler/painter.d.ts.map +1 -0
- package/dist/types/shared/src/behavior/spoiler/worklet.d.ts +2 -0
- package/dist/types/shared/src/behavior/spoiler/worklet.d.ts.map +1 -0
- package/dist/types/shared/src/behavior/toast.d.ts +72 -0
- package/dist/types/shared/src/behavior/toast.d.ts.map +1 -0
- package/dist/types/shared/src/lib/anchor.d.ts +31 -0
- package/dist/types/shared/src/lib/anchor.d.ts.map +1 -0
- package/dist/types/shared/src/lib/banner.d.ts +3 -0
- package/dist/types/shared/src/lib/banner.d.ts.map +1 -0
- package/dist/types/shared/src/lib/calendar/format.d.ts +7 -0
- package/dist/types/shared/src/lib/calendar/format.d.ts.map +1 -0
- package/dist/types/shared/src/lib/caret.d.ts +2 -0
- package/dist/types/shared/src/lib/caret.d.ts.map +1 -0
- package/dist/types/shared/src/lib/collapse.d.ts +9 -0
- package/dist/types/shared/src/lib/collapse.d.ts.map +1 -0
- package/dist/types/shared/src/lib/command-palette/hotkey.d.ts +9 -0
- package/dist/types/shared/src/lib/command-palette/hotkey.d.ts.map +1 -0
- package/dist/types/shared/src/lib/command-palette/match.d.ts +21 -0
- package/dist/types/shared/src/lib/command-palette/match.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-list.d.ts +7 -0
- package/dist/types/shared/src/lib/data-list.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-table/column-sizing-styles.d.ts +8 -0
- package/dist/types/shared/src/lib/data-table/column-sizing-styles.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-table/column-sizing.d.ts +22 -0
- package/dist/types/shared/src/lib/data-table/column-sizing.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-table/csv.d.ts +5 -0
- package/dist/types/shared/src/lib/data-table/csv.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-table/layout.d.ts +28 -0
- package/dist/types/shared/src/lib/data-table/layout.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-table/resize.d.ts +15 -0
- package/dist/types/shared/src/lib/data-table/resize.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-table/state.d.ts +103 -0
- package/dist/types/shared/src/lib/data-table/state.d.ts.map +1 -0
- package/dist/types/shared/src/lib/data-table/utils.d.ts +11 -0
- package/dist/types/shared/src/lib/data-table/utils.d.ts.map +1 -0
- package/dist/types/shared/src/lib/date-range-field/validity.d.ts +12 -0
- package/dist/types/shared/src/lib/date-range-field/validity.d.ts.map +1 -0
- package/dist/types/shared/src/lib/date.d.ts +28 -0
- package/dist/types/shared/src/lib/date.d.ts.map +1 -0
- package/dist/types/shared/src/lib/field-focus.d.ts +2 -0
- package/dist/types/shared/src/lib/field-focus.d.ts.map +1 -0
- package/dist/types/shared/src/lib/file-upload/select.d.ts +17 -0
- package/dist/types/shared/src/lib/file-upload/select.d.ts.map +1 -0
- package/dist/types/shared/src/lib/file-upload/size.d.ts +2 -0
- package/dist/types/shared/src/lib/file-upload/size.d.ts.map +1 -0
- package/dist/types/shared/src/lib/form/errors.d.ts +7 -0
- package/dist/types/shared/src/lib/form/errors.d.ts.map +1 -0
- package/dist/types/shared/src/lib/form/focus.d.ts +2 -0
- package/dist/types/shared/src/lib/form/focus.d.ts.map +1 -0
- package/dist/types/shared/src/lib/form/standard-schema.d.ts +23 -0
- package/dist/types/shared/src/lib/form/standard-schema.d.ts.map +1 -0
- package/dist/types/shared/src/lib/form/values.d.ts +3 -0
- package/dist/types/shared/src/lib/form/values.d.ts.map +1 -0
- package/dist/types/shared/src/lib/highlighter.d.ts +4 -0
- package/dist/types/shared/src/lib/highlighter.d.ts.map +1 -0
- package/dist/types/shared/src/lib/iris-origin.d.ts +6 -0
- package/dist/types/shared/src/lib/iris-origin.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/clip.d.ts +16 -0
- package/dist/types/shared/src/lib/lightbox/clip.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/download.d.ts +3 -0
- package/dist/types/shared/src/lib/lightbox/download.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/gesture.d.ts +26 -0
- package/dist/types/shared/src/lib/lightbox/gesture.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/paging.d.ts +9 -0
- package/dist/types/shared/src/lib/lightbox/paging.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/pose.d.ts +38 -0
- package/dist/types/shared/src/lib/lightbox/pose.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/source.d.ts +4 -0
- package/dist/types/shared/src/lib/lightbox/source.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/types.d.ts +16 -0
- package/dist/types/shared/src/lib/lightbox/types.d.ts.map +1 -0
- package/dist/types/shared/src/lib/lightbox/zoom.d.ts +40 -0
- package/dist/types/shared/src/lib/lightbox/zoom.d.ts.map +1 -0
- package/dist/types/shared/src/lib/meter-group.d.ts +5 -0
- package/dist/types/shared/src/lib/meter-group.d.ts.map +1 -0
- package/dist/types/shared/src/lib/overlay-anchor.d.ts +10 -0
- package/dist/types/shared/src/lib/overlay-anchor.d.ts.map +1 -0
- package/dist/types/shared/src/lib/pagination.d.ts +4 -0
- package/dist/types/shared/src/lib/pagination.d.ts.map +1 -0
- package/dist/types/shared/src/lib/pointer-corridor.d.ts +7 -0
- package/dist/types/shared/src/lib/pointer-corridor.d.ts.map +1 -0
- package/dist/types/shared/src/lib/qr-code-export.d.ts +6 -0
- package/dist/types/shared/src/lib/qr-code-export.d.ts.map +1 -0
- package/dist/types/shared/src/lib/range-calendar/limit.d.ts +3 -0
- package/dist/types/shared/src/lib/range-calendar/limit.d.ts.map +1 -0
- package/dist/types/shared/src/lib/rating.d.ts +2 -0
- package/dist/types/shared/src/lib/rating.d.ts.map +1 -0
- package/dist/types/shared/src/lib/relative-time.d.ts +2 -0
- package/dist/types/shared/src/lib/relative-time.d.ts.map +1 -0
- package/dist/types/shared/src/lib/scroll-area.d.ts +50 -0
- package/dist/types/shared/src/lib/scroll-area.d.ts.map +1 -0
- package/dist/types/shared/src/lib/scroll-restore.d.ts +34 -0
- package/dist/types/shared/src/lib/scroll-restore.d.ts.map +1 -0
- package/dist/types/shared/src/lib/toast-layout.d.ts +13 -0
- package/dist/types/shared/src/lib/toast-layout.d.ts.map +1 -0
- package/dist/types/shared/src/lib/tree/selection.d.ts +23 -0
- package/dist/types/shared/src/lib/tree/selection.d.ts.map +1 -0
- package/dist/types/shared/src/lib/tree-select/filter.d.ts +7 -0
- package/dist/types/shared/src/lib/tree-select/filter.d.ts.map +1 -0
- package/dist/types/shared/src/lib/virtual/choices.d.ts +59 -0
- package/dist/types/shared/src/lib/virtual/choices.d.ts.map +1 -0
- package/dist/types/shared/src/lib/virtual/collection.d.ts +25 -0
- package/dist/types/shared/src/lib/virtual/collection.d.ts.map +1 -0
- package/dist/types/shared/src/lib/virtual/flow.d.ts +18 -0
- package/dist/types/shared/src/lib/virtual/flow.d.ts.map +1 -0
- package/dist/types/shared/src/lib/virtual/list.d.ts +46 -0
- package/dist/types/shared/src/lib/virtual/list.d.ts.map +1 -0
- package/dist/types/shared/src/lib/virtual/navigation.d.ts +3 -0
- package/dist/types/shared/src/lib/virtual/navigation.d.ts.map +1 -0
- package/dist/types/shared/src/lib/virtual/tree.d.ts +31 -0
- package/dist/types/shared/src/lib/virtual/tree.d.ts.map +1 -0
- package/dist/types/shared/src/locale/en-US.d.ts +3 -0
- package/dist/types/shared/src/locale/en-US.d.ts.map +1 -0
- package/dist/types/shared/src/locale/index.d.ts +6 -0
- package/dist/types/shared/src/locale/index.d.ts.map +1 -0
- package/dist/types/shared/src/locale/types.d.ts +235 -0
- package/dist/types/shared/src/locale/types.d.ts.map +1 -0
- package/dist/types/shared/src/locale/zh-CN.d.ts +3 -0
- package/dist/types/shared/src/locale/zh-CN.d.ts.map +1 -0
- package/dist/types/shared/src/primitives/number-field/index.d.ts +155 -0
- package/dist/types/shared/src/primitives/number-field/index.d.ts.map +1 -0
- package/dist/types/shared/src/types/autocomplete.d.ts +14 -0
- package/dist/types/shared/src/types/autocomplete.d.ts.map +1 -0
- package/dist/types/shared/src/types/data-table.d.ts +169 -0
- package/dist/types/shared/src/types/data-table.d.ts.map +1 -0
- package/dist/types/shared/src/types/pagination.d.ts +23 -0
- package/dist/types/shared/src/types/pagination.d.ts.map +1 -0
- package/dist/types/shared/src/types/select.d.ts +14 -0
- package/dist/types/shared/src/types/select.d.ts.map +1 -0
- package/dist/types/shared/src/types/tree-select.d.ts +10 -0
- package/dist/types/shared/src/types/tree-select.d.ts.map +1 -0
- package/dist/types/shared/src/types/tree.d.ts +18 -0
- package/dist/types/shared/src/types/tree.d.ts.map +1 -0
- package/dist/types/shared/src/variants/autocomplete.d.ts +3 -0
- package/dist/types/shared/src/variants/autocomplete.d.ts.map +1 -0
- package/dist/types/shared/src/variants/editable.d.ts +52 -0
- package/dist/types/shared/src/variants/editable.d.ts.map +1 -0
- package/dist/types/shared/src/variants/float-button.d.ts +74 -0
- package/dist/types/shared/src/variants/float-button.d.ts.map +1 -0
- package/dist/types/shared/src/variants/split-button.d.ts +18 -0
- package/dist/types/shared/src/variants/split-button.d.ts.map +1 -0
- package/dist/types/vue/src/components/accordion/AccordionTrigger.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/anchor/Anchor.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/anchor/composables/useAnchor.d.ts +2 -7
- package/dist/types/vue/src/components/anchor/composables/useAnchor.d.ts.map +1 -1
- package/dist/types/vue/src/components/anchor/composables/useAnchorFollow.d.ts +1 -1
- package/dist/types/vue/src/components/anchor/composables/useAnchorFollow.d.ts.map +1 -1
- package/dist/types/vue/src/components/anchor/composables/useScrollSpy.d.ts +2 -5
- package/dist/types/vue/src/components/anchor/composables/useScrollSpy.d.ts.map +1 -1
- package/dist/types/vue/src/components/anchor/types.d.ts +1 -8
- package/dist/types/vue/src/components/anchor/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/autocomplete/autocomplete.variants.d.ts +1 -1
- package/dist/types/vue/src/components/autocomplete/autocomplete.variants.d.ts.map +1 -1
- package/dist/types/vue/src/components/autocomplete/types.d.ts +1 -13
- package/dist/types/vue/src/components/autocomplete/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/banner/utils/direction.d.ts +1 -2
- package/dist/types/vue/src/components/banner/utils/direction.d.ts.map +1 -1
- package/dist/types/vue/src/components/calendar/utils/format.d.ts +1 -6
- package/dist/types/vue/src/components/calendar/utils/format.d.ts.map +1 -1
- package/dist/types/vue/src/components/code-block/highlighter.d.ts +1 -3
- package/dist/types/vue/src/components/code-block/highlighter.d.ts.map +1 -1
- package/dist/types/vue/src/components/collapsible/CollapsibleTrigger.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/command-palette/composables/useCommandItems.d.ts +1 -1
- package/dist/types/vue/src/components/command-palette/utils/hotkey.d.ts +1 -8
- package/dist/types/vue/src/components/command-palette/utils/hotkey.d.ts.map +1 -1
- package/dist/types/vue/src/components/command-palette/utils/match.d.ts +5 -12
- package/dist/types/vue/src/components/command-palette/utils/match.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-list/composables/useDataList.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-list/utils/scroll.d.ts +1 -2
- package/dist/types/vue/src/components/data-list/utils/scroll.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/column-sizing-styles.d.ts +1 -3
- package/dist/types/vue/src/components/data-table/column-sizing-styles.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/column-sizing.d.ts +1 -21
- package/dist/types/vue/src/components/data-table/column-sizing.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/composables/useDataTable.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/composables/useTableColumns.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/composables/useTableDrag.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/composables/useTableExport.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/composables/useTableResize.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/composables/useTableResizeHandles.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/composables/useTableVirtual.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/types.d.ts +3 -153
- package/dist/types/vue/src/components/data-table/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/data-table/utils.d.ts +1 -9
- package/dist/types/vue/src/components/data-table/utils.d.ts.map +1 -1
- package/dist/types/vue/src/components/date-range-field/utils/validity.d.ts +1 -11
- package/dist/types/vue/src/components/date-range-field/utils/validity.d.ts.map +1 -1
- package/dist/types/vue/src/components/editable/editable.variants.d.ts +1 -1
- package/dist/types/vue/src/components/editable/editable.variants.d.ts.map +1 -1
- package/dist/types/vue/src/components/file-upload/utils/select.d.ts +1 -16
- package/dist/types/vue/src/components/file-upload/utils/select.d.ts.map +1 -1
- package/dist/types/vue/src/components/file-upload/utils/size.d.ts +1 -1
- package/dist/types/vue/src/components/file-upload/utils/size.d.ts.map +1 -1
- package/dist/types/vue/src/components/float-button/float-button.variants.d.ts +1 -1
- package/dist/types/vue/src/components/float-button/float-button.variants.d.ts.map +1 -1
- package/dist/types/vue/src/components/form/Form.vue.d.ts +1 -1
- package/dist/types/vue/src/components/form/composables/useForm.d.ts +9 -15
- package/dist/types/vue/src/components/form/composables/useForm.d.ts.map +1 -1
- package/dist/types/vue/src/components/form/standard-schema.d.ts +1 -22
- package/dist/types/vue/src/components/form/standard-schema.d.ts.map +1 -1
- package/dist/types/vue/src/components/form/utils/errors.d.ts +1 -6
- package/dist/types/vue/src/components/form/utils/errors.d.ts.map +1 -1
- package/dist/types/vue/src/components/form/utils/focus.d.ts +1 -1
- package/dist/types/vue/src/components/form/utils/focus.d.ts.map +1 -1
- package/dist/types/vue/src/components/form/utils/values.d.ts +1 -2
- package/dist/types/vue/src/components/form/utils/values.d.ts.map +1 -1
- package/dist/types/vue/src/components/form-field/FormField.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/composables/useLightboxHint.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/types.d.ts +1 -15
- package/dist/types/vue/src/components/lightbox/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/utils/clip.d.ts +1 -15
- package/dist/types/vue/src/components/lightbox/utils/clip.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/utils/download.d.ts +1 -2
- package/dist/types/vue/src/components/lightbox/utils/download.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/utils/gesture.d.ts +1 -25
- package/dist/types/vue/src/components/lightbox/utils/gesture.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/utils/paging.d.ts +1 -8
- package/dist/types/vue/src/components/lightbox/utils/paging.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/utils/pose.d.ts +1 -37
- package/dist/types/vue/src/components/lightbox/utils/pose.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/utils/source.d.ts +1 -3
- package/dist/types/vue/src/components/lightbox/utils/source.d.ts.map +1 -1
- package/dist/types/vue/src/components/lightbox/utils/zoom.d.ts +1 -39
- package/dist/types/vue/src/components/lightbox/utils/zoom.d.ts.map +1 -1
- package/dist/types/vue/src/components/meter-group/utils/tones.d.ts +1 -3
- package/dist/types/vue/src/components/meter-group/utils/tones.d.ts.map +1 -1
- package/dist/types/vue/src/components/month-grid/MonthGrid.vue.d.ts +1 -1
- package/dist/types/vue/src/components/multi-select/MultiSelect.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/pagination/composables/usePagination.d.ts +2 -2
- package/dist/types/vue/src/components/pagination/composables/usePagination.d.ts.map +1 -1
- package/dist/types/vue/src/components/pagination/types.d.ts +1 -22
- package/dist/types/vue/src/components/pagination/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/pagination/utils/ranges.d.ts +1 -2
- package/dist/types/vue/src/components/pagination/utils/ranges.d.ts.map +1 -1
- package/dist/types/vue/src/components/password-input/PasswordInput.vue.d.ts +4 -1
- package/dist/types/vue/src/components/password-input/PasswordInput.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/prev-next/PrevNextLink.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/qr-code/export.d.ts +1 -2
- package/dist/types/vue/src/components/qr-code/export.d.ts.map +1 -1
- package/dist/types/vue/src/components/range-calendar/utils/limit.d.ts +1 -2
- package/dist/types/vue/src/components/range-calendar/utils/limit.d.ts.map +1 -1
- package/dist/types/vue/src/components/range-slider/RangeSlider.vue.d.ts +2 -2
- package/dist/types/vue/src/components/rating/utils/fill.d.ts +1 -1
- package/dist/types/vue/src/components/rating/utils/fill.d.ts.map +1 -1
- package/dist/types/vue/src/components/ripple/useRipple.d.ts.map +1 -1
- package/dist/types/vue/src/components/scroll-area/ScrollArea.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/scroll-area/composables/useEdgeShadow.d.ts +2 -1
- package/dist/types/vue/src/components/scroll-area/composables/useEdgeShadow.d.ts.map +1 -1
- package/dist/types/vue/src/components/scroll-area/composables/useLayerLock.d.ts.map +1 -1
- package/dist/types/vue/src/components/scroll-area/composables/useWheelRedirect.d.ts.map +1 -1
- package/dist/types/vue/src/components/scroll-area/scroll-restore.d.ts +1 -33
- package/dist/types/vue/src/components/scroll-area/scroll-restore.d.ts.map +1 -1
- package/dist/types/vue/src/components/search-input/SearchInput.vue.d.ts +4 -1
- package/dist/types/vue/src/components/search-input/SearchInput.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/select/types.d.ts +1 -13
- package/dist/types/vue/src/components/select/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/slider/Slider.vue.d.ts +2 -2
- package/dist/types/vue/src/components/split-button/split-button.variants.d.ts +1 -1
- package/dist/types/vue/src/components/split-button/split-button.variants.d.ts.map +1 -1
- package/dist/types/vue/src/components/spoiler/SpoilerPainter.d.ts +1 -34
- package/dist/types/vue/src/components/spoiler/SpoilerPainter.d.ts.map +1 -1
- package/dist/types/vue/src/components/spoiler/utils/irisOrigin.d.ts +1 -5
- package/dist/types/vue/src/components/spoiler/utils/irisOrigin.d.ts.map +1 -1
- package/dist/types/vue/src/components/spoiler/worklet.d.ts +1 -1
- package/dist/types/vue/src/components/spoiler/worklet.d.ts.map +1 -1
- package/dist/types/vue/src/components/table/Table.vue.d.ts +6 -3
- package/dist/types/vue/src/components/table/Table.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/tabs/TabsList.vue.d.ts +6 -3
- package/dist/types/vue/src/components/tabs/TabsList.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/time/utils/relativeTime.d.ts +1 -1
- package/dist/types/vue/src/components/time/utils/relativeTime.d.ts.map +1 -1
- package/dist/types/vue/src/components/toast/composables/useToastLayout.d.ts +4 -11
- package/dist/types/vue/src/components/toast/composables/useToastLayout.d.ts.map +1 -1
- package/dist/types/vue/src/components/toast/store.d.ts +14 -62
- package/dist/types/vue/src/components/toast/store.d.ts.map +1 -1
- package/dist/types/vue/src/components/tree/composables/useTree.d.ts.map +1 -1
- package/dist/types/vue/src/components/tree/types.d.ts +1 -17
- package/dist/types/vue/src/components/tree/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/tree/utils/selection.d.ts +1 -15
- package/dist/types/vue/src/components/tree/utils/selection.d.ts.map +1 -1
- package/dist/types/vue/src/components/tree-select/types.d.ts +1 -9
- package/dist/types/vue/src/components/tree-select/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/tree-select/utils/filterTree.d.ts +1 -6
- package/dist/types/vue/src/components/tree-select/utils/filterTree.d.ts.map +1 -1
- package/dist/types/vue/src/components/virtual-list/composables/useVirtualList.d.ts +1 -1
- package/dist/types/vue/src/components/virtual-list/composables/useVirtualList.d.ts.map +1 -1
- package/dist/types/vue/src/components/visually-hidden/VisuallyHidden.vue.d.ts +4 -1
- package/dist/types/vue/src/components/visually-hidden/VisuallyHidden.vue.d.ts.map +1 -1
- package/dist/types/vue/src/lib/caret.d.ts +1 -1
- package/dist/types/vue/src/lib/caret.d.ts.map +1 -1
- package/dist/types/vue/src/lib/collapse.d.ts +2 -8
- package/dist/types/vue/src/lib/collapse.d.ts.map +1 -1
- package/dist/types/vue/src/lib/date.d.ts +1 -27
- package/dist/types/vue/src/lib/date.d.ts.map +1 -1
- package/dist/types/vue/src/lib/field-focus.d.ts +1 -1
- package/dist/types/vue/src/lib/field-focus.d.ts.map +1 -1
- package/dist/types/vue/src/lib/overlay-anchor.d.ts +2 -7
- package/dist/types/vue/src/lib/overlay-anchor.d.ts.map +1 -1
- package/dist/types/vue/src/lib/pointer-corridor.d.ts +1 -6
- package/dist/types/vue/src/lib/pointer-corridor.d.ts.map +1 -1
- package/dist/types/vue/src/lib/reka/useVirtualChoices.d.ts +3 -11
- package/dist/types/vue/src/lib/reka/useVirtualChoices.d.ts.map +1 -1
- package/dist/types/vue/src/lib/reka/useVirtualTree.d.ts +1 -1
- package/dist/types/vue/src/lib/reka/useVirtualTree.d.ts.map +1 -1
- package/dist/types/vue/src/lib/virtual/navigation.d.ts +1 -2
- package/dist/types/vue/src/lib/virtual/navigation.d.ts.map +1 -1
- package/dist/types/vue/src/lib/virtual/useVirtualCollection.d.ts +1 -1
- package/dist/types/vue/src/lib/virtual/useVirtualCollection.d.ts.map +1 -1
- package/dist/types/vue/src/lib/virtual/useVirtualWindow.d.ts +2 -15
- package/dist/types/vue/src/lib/virtual/useVirtualWindow.d.ts.map +1 -1
- package/dist/types/vue/src/locale/en-US.d.ts +1 -2
- package/dist/types/vue/src/locale/en-US.d.ts.map +1 -1
- package/dist/types/vue/src/locale/index.d.ts +3 -4
- package/dist/types/vue/src/locale/index.d.ts.map +1 -1
- package/dist/types/vue/src/locale/types.d.ts +1 -234
- package/dist/types/vue/src/locale/types.d.ts.map +1 -1
- package/dist/types/vue/src/locale/zh-CN.d.ts +1 -2
- package/dist/types/vue/src/locale/zh-CN.d.ts.map +1 -1
- package/dist/types/vue/src/primitives/number-field/NumberFieldDecrement.vue.d.ts +17 -0
- package/dist/types/vue/src/primitives/number-field/NumberFieldDecrement.vue.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/number-field/NumberFieldIncrement.vue.d.ts +17 -0
- package/dist/types/vue/src/primitives/number-field/NumberFieldIncrement.vue.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/number-field/NumberFieldInput.vue.d.ts +16 -0
- package/dist/types/vue/src/primitives/number-field/NumberFieldInput.vue.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/number-field/NumberFieldRoot.vue.d.ts +47 -0
- package/dist/types/vue/src/primitives/number-field/NumberFieldRoot.vue.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/number-field/context.d.ts +41 -0
- package/dist/types/vue/src/primitives/number-field/context.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/number-field/index.d.ts +5 -0
- package/dist/types/vue/src/primitives/number-field/index.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/utils/timers.d.ts +6 -0
- package/dist/types/vue/src/primitives/utils/timers.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/utils/usePrimitiveElement.d.ts +6 -0
- package/dist/types/vue/src/primitives/utils/usePrimitiveElement.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/utils/useVModel.d.ts +7 -0
- package/dist/types/vue/src/primitives/utils/useVModel.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/visually-hidden/VisuallyHiddenInput.d.ts +66 -0
- package/dist/types/vue/src/primitives/visually-hidden/VisuallyHiddenInput.d.ts.map +1 -0
- package/dist/types/vue/src/primitives/visually-hidden/VisuallyHiddenInputBubble.vue.d.ts +28 -0
- package/dist/types/vue/src/primitives/visually-hidden/VisuallyHiddenInputBubble.vue.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/components/accordion/AccordionTrigger.vue +9 -1
- package/src/components/anchor/Anchor.vue +13 -9
- package/src/components/anchor/composables/useAnchor.ts +3 -12
- package/src/components/anchor/composables/useAnchorFollow.ts +10 -63
- package/src/components/anchor/composables/useScrollSpy.ts +22 -38
- package/src/components/anchor/types.ts +1 -8
- package/src/components/autocomplete/autocomplete.variants.ts +1 -1
- package/src/components/autocomplete/composables/useAutocomplete.ts +1 -1
- package/src/components/autocomplete/types.ts +1 -16
- package/src/components/banner/utils/direction.ts +1 -10
- package/src/components/calendar/utils/format.ts +1 -23
- package/src/components/code-block/highlighter.ts +1 -98
- package/src/components/collapsible/CollapsibleTrigger.vue +8 -1
- package/src/components/command-palette/utils/hotkey.ts +1 -27
- package/src/components/command-palette/utils/match.ts +5 -75
- package/src/components/data-list/composables/useDataList.ts +2 -4
- package/src/components/data-list/utils/scroll.ts +1 -26
- package/src/components/data-table/column-sizing-styles.ts +1 -40
- package/src/components/data-table/column-sizing.ts +1 -101
- package/src/components/data-table/composables/useDataTable.ts +103 -123
- package/src/components/data-table/composables/useTableColumns.ts +38 -113
- package/src/components/data-table/composables/useTableDrag.ts +21 -11
- package/src/components/data-table/composables/useTableExport.ts +8 -32
- package/src/components/data-table/composables/useTableResize.ts +13 -17
- package/src/components/data-table/composables/useTableResizeHandles.ts +6 -21
- package/src/components/data-table/types.ts +15 -155
- package/src/components/data-table/utils.ts +1 -75
- package/src/components/date-range-field/utils/validity.ts +1 -21
- package/src/components/editable/editable.variants.ts +1 -1
- package/src/components/file-upload/utils/select.ts +1 -58
- package/src/components/file-upload/utils/size.ts +1 -16
- package/src/components/float-button/float-button.variants.ts +1 -1
- package/src/components/form/composables/useForm.ts +24 -135
- package/src/components/form/standard-schema.ts +1 -26
- package/src/components/form/utils/errors.ts +1 -48
- package/src/components/form/utils/focus.ts +1 -10
- package/src/components/form/utils/values.ts +1 -23
- package/src/components/form-field/FormField.vue +3 -2
- package/src/components/lightbox/composables/useLightboxHint.ts +6 -1
- package/src/components/lightbox/types.ts +1 -14
- package/src/components/lightbox/utils/clip.ts +1 -117
- package/src/components/lightbox/utils/download.ts +1 -29
- package/src/components/lightbox/utils/gesture.ts +1 -54
- package/src/components/lightbox/utils/paging.ts +1 -33
- package/src/components/lightbox/utils/pose.ts +1 -142
- package/src/components/lightbox/utils/source.ts +1 -17
- package/src/components/lightbox/utils/zoom.ts +1 -127
- package/src/components/meter-group/utils/tones.ts +1 -14
- package/src/components/multi-select/MultiSelect.vue +1 -2
- package/src/components/number-input/NumberInput.vue +2 -2
- package/src/components/pagination/composables/usePagination.ts +2 -3
- package/src/components/pagination/types.ts +1 -19
- package/src/components/pagination/utils/ranges.ts +1 -12
- package/src/components/password-input/PasswordInput.vue +6 -0
- package/src/components/prev-next/PrevNext.vue +1 -1
- package/src/components/prev-next/PrevNextLink.vue +1 -1
- package/src/components/qr-code/export.ts +1 -65
- package/src/components/range-calendar/utils/limit.ts +1 -11
- package/src/components/rating/utils/fill.ts +1 -4
- package/src/components/ripple/useRipple.ts +10 -198
- package/src/components/scroll-area/ScrollArea.vue +6 -18
- package/src/components/scroll-area/composables/useEdgeShadow.ts +7 -16
- package/src/components/scroll-area/composables/useLayerLock.ts +2 -9
- package/src/components/scroll-area/composables/useWheelRedirect.ts +2 -10
- package/src/components/scroll-area/scroll-restore.ts +1 -148
- package/src/components/search-input/SearchInput.vue +6 -0
- package/src/components/select/types.ts +1 -23
- package/src/components/split-button/split-button.variants.ts +1 -1
- package/src/components/spoiler/SpoilerPainter.ts +1 -197
- package/src/components/spoiler/utils/irisOrigin.ts +1 -40
- package/src/components/spoiler/worklet.ts +1 -199
- package/src/components/table/Table.vue +9 -0
- package/src/components/tabs/TabsList.vue +9 -0
- package/src/components/time/utils/relativeTime.ts +1 -20
- package/src/components/toast/composables/useToastLayout.ts +12 -24
- package/src/components/toast/store.ts +16 -228
- package/src/components/tree/composables/useTree.ts +17 -33
- package/src/components/tree/types.ts +1 -20
- package/src/components/tree/utils/selection.ts +1 -78
- package/src/components/tree-select/types.ts +1 -34
- package/src/components/tree-select/utils/filterTree.ts +1 -19
- package/src/components/virtual-list/composables/useVirtualList.ts +16 -42
- package/src/components/visually-hidden/VisuallyHidden.vue +21 -3
- package/src/lib/caret.ts +1 -48
- package/src/lib/collapse.ts +6 -29
- package/src/lib/date.ts +1 -111
- package/src/lib/field-focus.ts +1 -36
- package/src/lib/overlay-anchor.ts +11 -37
- package/src/lib/pointer-corridor.ts +1 -26
- package/src/lib/reka/useVirtualChoices.ts +55 -133
- package/src/lib/reka/useVirtualTree.ts +22 -65
- package/src/lib/virtual/navigation.ts +1 -26
- package/src/lib/virtual/useVirtualCollection.ts +28 -47
- package/src/lib/virtual/useVirtualWindow.ts +15 -25
- package/src/locale/en-US.ts +1 -220
- package/src/locale/index.ts +9 -53
- package/src/locale/types.ts +1 -225
- package/src/locale/zh-CN.ts +1 -215
- package/src/primitives/number-field/LICENSE +21 -0
- package/src/primitives/number-field/NumberFieldDecrement.vue +21 -0
- package/src/primitives/number-field/NumberFieldIncrement.vue +21 -0
- package/src/primitives/number-field/NumberFieldInput.vue +114 -0
- package/src/primitives/number-field/NumberFieldRoot.vue +169 -0
- package/src/primitives/number-field/context.ts +111 -0
- package/src/primitives/number-field/index.ts +14 -0
- package/src/primitives/utils/LICENSE +44 -0
- package/src/primitives/utils/timers.ts +6 -0
- package/src/primitives/utils/usePrimitiveElement.ts +12 -0
- package/src/primitives/utils/useVModel.ts +37 -0
- package/src/primitives/visually-hidden/LICENSE +21 -0
- package/src/primitives/visually-hidden/VisuallyHiddenInput.ts +97 -0
- package/src/primitives/visually-hidden/VisuallyHiddenInputBubble.vue +49 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import type { UiMessages } from '../../locale/types'
|
|
2
|
+
import type {
|
|
3
|
+
DataTableColumn,
|
|
4
|
+
DataTableFilter,
|
|
5
|
+
DataTableKey,
|
|
6
|
+
DataTableSort,
|
|
7
|
+
} from '../../types/data-table'
|
|
8
|
+
import { rowId, rowKey } from './utils'
|
|
9
|
+
|
|
10
|
+
export interface DataTableEngineModels {
|
|
11
|
+
sorting: DataTableSort[]
|
|
12
|
+
filter: string
|
|
13
|
+
columnFilters: DataTableFilter[]
|
|
14
|
+
grouping: string[]
|
|
15
|
+
selected: DataTableKey[]
|
|
16
|
+
expanded: DataTableKey[]
|
|
17
|
+
expandedGroups: string[]
|
|
18
|
+
hiddenColumns: string[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface DataTableSelectionRow<T> {
|
|
22
|
+
id: string
|
|
23
|
+
original: T
|
|
24
|
+
getCanSelect: () => boolean
|
|
25
|
+
getIsSelected: () => boolean
|
|
26
|
+
getIsSomeSelected: () => boolean
|
|
27
|
+
getLeafRows: () => DataTableSelectionRow<T>[]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function keyOf<T>(row: T, field: keyof T | ((row: T) => DataTableKey)): DataTableKey {
|
|
31
|
+
return typeof field === 'function' ? field(row) : (row[field] as DataTableKey)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function labelOf<T>(
|
|
35
|
+
row: T,
|
|
36
|
+
label: keyof T | ((row: T) => string) | undefined,
|
|
37
|
+
key: (row: T) => DataTableKey,
|
|
38
|
+
) {
|
|
39
|
+
return String(
|
|
40
|
+
typeof label === 'function' ? label(row) : label === undefined ? key(row) : row[label],
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function valueOf<T>(row: T, column: DataTableColumn<T>) {
|
|
45
|
+
return column.accessor ? column.accessor(row) : row[column.field ?? (column.key as keyof T)]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function displayValue<T>(row: T, column: DataTableColumn<T>) {
|
|
49
|
+
const value = valueOf(row, column)
|
|
50
|
+
return column.format ? column.format(value, row) : value == null ? '—' : String(value)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function compareValues(left: unknown, right: unknown, collator: Intl.Collator) {
|
|
54
|
+
if (typeof left === 'number' && typeof right === 'number') return left - right
|
|
55
|
+
if (left instanceof Date && right instanceof Date) return left.getTime() - right.getTime()
|
|
56
|
+
return collator.compare(String(left), String(right))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function engineSorting(sorting: DataTableSort[]) {
|
|
60
|
+
return sorting.map(sort => ({ id: sort.key, desc: sort.desc }))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function modelSorting(sorting: { id: string; desc: boolean }[]): DataTableSort[] {
|
|
64
|
+
return sorting.map(sort => ({ key: sort.id, desc: sort.desc }))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function engineSelection(selected: DataTableKey[]) {
|
|
68
|
+
return Object.fromEntries(selected.map(key => [rowId(key), true as const]))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function modelSelection(selection: Record<string, boolean>) {
|
|
72
|
+
return Object.keys(selection)
|
|
73
|
+
.filter(key => selection[key])
|
|
74
|
+
.map(rowKey)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function engineColumnFilters<T>(leaves: DataTableColumn<T>[], filters: DataTableFilter[]) {
|
|
78
|
+
return filters
|
|
79
|
+
.filter(filter => leaves.some(column => column.key === filter.key))
|
|
80
|
+
.map(filter => ({ id: filter.key, value: filter.value }))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function engineGrouping<T>(leaves: DataTableColumn<T>[], grouping: string[]) {
|
|
84
|
+
return grouping.filter(key => leaves.some(column => column.key === key))
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function engineExpanded(expanded: DataTableKey[], groups: string[]) {
|
|
88
|
+
return Object.fromEntries([...expanded.map(rowId), ...groups].map(key => [key, true]))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function engineVisibility(hidden: string[]) {
|
|
92
|
+
return Object.fromEntries(hidden.map(key => [key, false]))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function engineState<T>(
|
|
96
|
+
leaves: DataTableColumn<T>[],
|
|
97
|
+
models: DataTableEngineModels,
|
|
98
|
+
page: number,
|
|
99
|
+
pageSize: number,
|
|
100
|
+
) {
|
|
101
|
+
return {
|
|
102
|
+
sorting: engineSorting(models.sorting),
|
|
103
|
+
globalFilter: models.filter.trim(),
|
|
104
|
+
columnFilters: engineColumnFilters(leaves, models.columnFilters),
|
|
105
|
+
grouping: engineGrouping(leaves, models.grouping),
|
|
106
|
+
expanded: engineExpanded(models.expanded, models.expandedGroups),
|
|
107
|
+
pagination: { pageIndex: page - 1, pageSize },
|
|
108
|
+
rowSelection: engineSelection(models.selected),
|
|
109
|
+
columnVisibility: engineVisibility(models.hiddenColumns),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function orderColumns<T>(leaves: DataTableColumn<T>[], hidden: string[], order: string[]) {
|
|
114
|
+
const visible = leaves.filter(column => !hidden.includes(column.key))
|
|
115
|
+
const ranking = [...new Set([...order, ...visible.map(column => column.key)])]
|
|
116
|
+
return visible.sort((a, b) => {
|
|
117
|
+
const rank = (column: DataTableColumn<T>) =>
|
|
118
|
+
column.pin === 'start' ? 0 : column.pin === 'end' ? 2 : 1
|
|
119
|
+
return rank(a) - rank(b) || ranking.indexOf(a.key) - ranking.indexOf(b.key)
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function toggleKey<K>(list: K[], key: K, next: boolean) {
|
|
124
|
+
return next ? [...new Set([...list, key])] : list.filter(item => item !== key)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function nextColumnFilters(filters: DataTableFilter[], column: string, value: unknown) {
|
|
128
|
+
const next = filters.filter(filter => filter.key !== column)
|
|
129
|
+
if (value != null && value !== '' && !(Array.isArray(value) && !value.length))
|
|
130
|
+
next.push({ key: column, value })
|
|
131
|
+
return next
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function totalRows(
|
|
135
|
+
manual: boolean | undefined,
|
|
136
|
+
total: number | undefined,
|
|
137
|
+
supplied: number,
|
|
138
|
+
processed: () => number,
|
|
139
|
+
) {
|
|
140
|
+
return manual ? Math.max(0, Math.floor(Number.isFinite(total) ? total! : supplied)) : processed()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function pageCount(total: number, pageSize: number) {
|
|
144
|
+
return Math.max(1, Math.ceil(total / pageSize))
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function canGoNext(
|
|
148
|
+
knownTotal: boolean,
|
|
149
|
+
page: number,
|
|
150
|
+
count: number,
|
|
151
|
+
hasNextPage: boolean | undefined,
|
|
152
|
+
rows: number,
|
|
153
|
+
pageSize: number,
|
|
154
|
+
) {
|
|
155
|
+
return knownTotal ? page < count : (hasNextPage ?? rows >= pageSize)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function clampedPage(
|
|
159
|
+
pagination: boolean | undefined,
|
|
160
|
+
loading: boolean | undefined,
|
|
161
|
+
knownTotal: boolean,
|
|
162
|
+
page: number,
|
|
163
|
+
count: number,
|
|
164
|
+
) {
|
|
165
|
+
return pagination && !loading && knownTotal && page > count ? count : undefined
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function uniqueSelectable<R extends { id: string; getCanSelect: () => boolean }>(rows: R[]) {
|
|
169
|
+
return [...new Map(rows.filter(row => row.getCanSelect()).map(row => [row.id, row])).values()]
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function selectionState<R extends DataTableSelectionRow<unknown>>(eligible: R[]) {
|
|
173
|
+
if (!eligible.length) return false
|
|
174
|
+
const count = eligible.filter(row => row.getIsSelected()).length
|
|
175
|
+
return count === eligible.length
|
|
176
|
+
? true
|
|
177
|
+
: count || eligible.some(row => row.getIsSomeSelected())
|
|
178
|
+
? ('indeterminate' as const)
|
|
179
|
+
: false
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function toggleSelection<T>(
|
|
183
|
+
selected: DataTableKey[],
|
|
184
|
+
rows: DataTableSelectionRow<T>[],
|
|
185
|
+
value: boolean | 'indeterminate',
|
|
186
|
+
cascade: boolean,
|
|
187
|
+
key: (row: T) => DataTableKey,
|
|
188
|
+
) {
|
|
189
|
+
const keys = new Set(selected)
|
|
190
|
+
for (const row of rows) {
|
|
191
|
+
const descendants = cascade ? [row, ...row.getLeafRows()] : [row]
|
|
192
|
+
for (const item of descendants)
|
|
193
|
+
if (item.getCanSelect()) {
|
|
194
|
+
if (value === true) keys.add(key(item.original))
|
|
195
|
+
else keys.delete(key(item.original))
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return [...keys]
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function sortLabel(next: string | false | undefined, messages: UiMessages['table']) {
|
|
202
|
+
return next === 'asc' ? messages.sortAsc : next === 'desc' ? messages.sortDesc : messages.sortNone
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function ariaSort(sorting: 'asc' | 'desc' | false) {
|
|
206
|
+
return sorting
|
|
207
|
+
? sorting === 'asc'
|
|
208
|
+
? ('ascending' as const)
|
|
209
|
+
: ('descending' as const)
|
|
210
|
+
: undefined
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function tableQuery(
|
|
214
|
+
page: number,
|
|
215
|
+
pageSize: number,
|
|
216
|
+
models: Pick<DataTableEngineModels, 'sorting' | 'filter' | 'columnFilters' | 'grouping'>,
|
|
217
|
+
) {
|
|
218
|
+
return {
|
|
219
|
+
page,
|
|
220
|
+
pageSize,
|
|
221
|
+
sorting: models.sorting.map(sort => ({ ...sort })),
|
|
222
|
+
filter: models.filter,
|
|
223
|
+
columnFilters: models.columnFilters.map(filter => ({ ...filter })),
|
|
224
|
+
grouping: [...models.grouping],
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { DataTableColumn, DataTableFilterMode, DataTableKey } from '../../types/data-table'
|
|
2
|
+
|
|
3
|
+
export function rowId(key: DataTableKey) {
|
|
4
|
+
return `${typeof key}:${key}`
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function rowKey(id: string): DataTableKey {
|
|
8
|
+
return id.startsWith('number:') ? Number(id.slice(7)) : id.slice(7)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function positiveInteger(value: number, fallback: number) {
|
|
12
|
+
return Number.isFinite(value) ? Math.max(1, Math.floor(value)) : fallback
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function cssSize(value: number | string | undefined) {
|
|
16
|
+
return typeof value === 'number' ? `${value}px` : value
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type DataTableActionEvent = Pick<
|
|
20
|
+
Event,
|
|
21
|
+
'target' | 'currentTarget' | 'defaultPrevented' | 'type'
|
|
22
|
+
>
|
|
23
|
+
|
|
24
|
+
export function isRowAction(event: DataTableActionEvent) {
|
|
25
|
+
const target = event.target as HTMLElement | null
|
|
26
|
+
if (!target || event.defaultPrevented) return false
|
|
27
|
+
if (event.type === 'keydown') return target === event.currentTarget
|
|
28
|
+
const control = target.closest(
|
|
29
|
+
'a, button, input, select, textarea, label, [role="button"], [role="checkbox"], [role="switch"], [contenteditable]:not([contenteditable="false"]), [tabindex]',
|
|
30
|
+
)
|
|
31
|
+
return !control || control === event.currentTarget
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function flattenColumns<T>(columns: DataTableColumn<T>[]): DataTableColumn<T>[] {
|
|
35
|
+
return columns.flatMap(column =>
|
|
36
|
+
column.children?.length ? flattenColumns(column.children) : [column],
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
export function filterValue(
|
|
40
|
+
value: unknown,
|
|
41
|
+
filter: unknown,
|
|
42
|
+
mode: DataTableFilterMode = 'contains',
|
|
43
|
+
locale = 'en',
|
|
44
|
+
) {
|
|
45
|
+
if (mode === 'equals') return Object.is(value, filter)
|
|
46
|
+
if (mode === 'in') return Array.isArray(filter) && filter.some(item => Object.is(item, value))
|
|
47
|
+
if (mode === 'range') {
|
|
48
|
+
if (!Array.isArray(filter)) return true
|
|
49
|
+
const numeric = value instanceof Date ? value.getTime() : Number(value)
|
|
50
|
+
const bound = (value: unknown) => (value instanceof Date ? value.getTime() : Number(value))
|
|
51
|
+
return (
|
|
52
|
+
value != null &&
|
|
53
|
+
Number.isFinite(numeric) &&
|
|
54
|
+
(filter[0] == null || numeric >= bound(filter[0])) &&
|
|
55
|
+
(filter[1] == null || numeric <= bound(filter[1]))
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
return String(value ?? '')
|
|
59
|
+
.toLocaleLowerCase(locale)
|
|
60
|
+
.includes(String(filter ?? '').toLocaleLowerCase(locale))
|
|
61
|
+
}
|
|
62
|
+
export function aggregate<T>(
|
|
63
|
+
rows: T[],
|
|
64
|
+
column: DataTableColumn<T>,
|
|
65
|
+
valueOf: (row: T, column: DataTableColumn<T>) => unknown,
|
|
66
|
+
) {
|
|
67
|
+
if (typeof column.aggregate === 'function') return column.aggregate(rows)
|
|
68
|
+
if (!column.aggregate) return undefined
|
|
69
|
+
if (column.aggregate === 'count') return rows.length
|
|
70
|
+
const values = rows.map(row => valueOf(row, column))
|
|
71
|
+
if (column.aggregate === 'uniqueCount') return new Set(values).size
|
|
72
|
+
const numbers = values.filter(
|
|
73
|
+
(value): value is number => typeof value === 'number' && Number.isFinite(value),
|
|
74
|
+
)
|
|
75
|
+
if (!numbers.length) return column.aggregate === 'sum' ? 0 : undefined
|
|
76
|
+
if (column.aggregate === 'min') return numbers.reduce((a, b) => Math.min(a, b))
|
|
77
|
+
if (column.aggregate === 'max') return numbers.reduce((a, b) => Math.max(a, b))
|
|
78
|
+
const sum = numbers.reduce((a, b) => a + b, 0)
|
|
79
|
+
return column.aggregate === 'mean' ? sum / numbers.length : sum
|
|
80
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date'
|
|
2
|
+
|
|
3
|
+
interface Bounds {
|
|
4
|
+
min?: DateValue
|
|
5
|
+
max?: DateValue
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Parts {
|
|
9
|
+
start?: DateValue
|
|
10
|
+
end?: DateValue
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function outside(value: DateValue | undefined, { min, max }: Bounds) {
|
|
14
|
+
if (!value) return false
|
|
15
|
+
return (!!min && value.compare(min) < 0) || (!!max && value.compare(max) > 0)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isRangeInvalid({ start, end }: Parts, bounds: Bounds) {
|
|
19
|
+
if (outside(start, bounds) || outside(end, bounds)) return true
|
|
20
|
+
return !!start && !!end && start.compare(end) > 0
|
|
21
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CalendarDate,
|
|
3
|
+
CalendarDateTime,
|
|
4
|
+
Time,
|
|
5
|
+
parseDate,
|
|
6
|
+
parseDateTime,
|
|
7
|
+
parseTime,
|
|
8
|
+
type DateValue,
|
|
9
|
+
} from '@internationalized/date'
|
|
10
|
+
|
|
11
|
+
export type DateGranularity = 'day' | 'hour' | 'minute' | 'second'
|
|
12
|
+
export type TimeGranularity = 'hour' | 'minute' | 'second'
|
|
13
|
+
|
|
14
|
+
const TIME_LENGTH: Record<TimeGranularity, number> = {
|
|
15
|
+
hour: 'HH:mm'.length,
|
|
16
|
+
minute: 'HH:mm'.length,
|
|
17
|
+
second: 'HH:mm:ss'.length,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function parseTimeValue(value: string | null | undefined): Time | undefined {
|
|
21
|
+
if (!value) return undefined
|
|
22
|
+
try {
|
|
23
|
+
return parseTime(value)
|
|
24
|
+
} catch {
|
|
25
|
+
return undefined
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function formatTimeValue(
|
|
30
|
+
value: { hour: number; minute: number; second: number },
|
|
31
|
+
granularity: TimeGranularity = 'minute',
|
|
32
|
+
): string {
|
|
33
|
+
return new Time(value.hour, value.minute, value.second)
|
|
34
|
+
.toString()
|
|
35
|
+
.slice(0, TIME_LENGTH[granularity])
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function splitDateTime(value: string | null | undefined) {
|
|
39
|
+
if (!value) return { date: null, time: null }
|
|
40
|
+
const [date, time] = value.split('T')
|
|
41
|
+
return { date: date || null, time: time || null }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function joinDateTime(date: string | null, time: string | null) {
|
|
45
|
+
return date && time ? `${date}T${time}` : null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface DateRangeValue {
|
|
49
|
+
start: string | null
|
|
50
|
+
end: string | null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface DateRangeParts {
|
|
54
|
+
start: DateValue | undefined
|
|
55
|
+
end: DateValue | undefined
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const LENGTH: Record<DateGranularity, number> = {
|
|
59
|
+
day: 'YYYY-MM-DD'.length,
|
|
60
|
+
hour: 'YYYY-MM-DDTHH:mm'.length,
|
|
61
|
+
minute: 'YYYY-MM-DDTHH:mm'.length,
|
|
62
|
+
second: 'YYYY-MM-DDTHH:mm:ss'.length,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function parseDateValue(
|
|
66
|
+
value: string | null | undefined,
|
|
67
|
+
granularity: DateGranularity = 'day',
|
|
68
|
+
): DateValue | undefined {
|
|
69
|
+
if (!value) return undefined
|
|
70
|
+
try {
|
|
71
|
+
if (granularity === 'day') return parseDate(value.slice(0, LENGTH.day))
|
|
72
|
+
return value.includes('T')
|
|
73
|
+
? parseDateTime(value)
|
|
74
|
+
: parseDate(value).toDate('UTC')
|
|
75
|
+
? toDateTime(parseDate(value))
|
|
76
|
+
: undefined
|
|
77
|
+
} catch {
|
|
78
|
+
return undefined
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function formatDateValue(value: DateValue, granularity: DateGranularity = 'day'): string {
|
|
83
|
+
if (granularity === 'day') return new CalendarDate(value.year, value.month, value.day).toString()
|
|
84
|
+
const time = value instanceof CalendarDateTime ? value : toDateTime(value)
|
|
85
|
+
return time.toString().slice(0, LENGTH[granularity])
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function parseDateRange(
|
|
89
|
+
value: DateRangeValue | null | undefined,
|
|
90
|
+
granularity: DateGranularity = 'day',
|
|
91
|
+
): DateRangeParts {
|
|
92
|
+
return {
|
|
93
|
+
start: parseDateValue(value?.start, granularity),
|
|
94
|
+
end: parseDateValue(value?.end, granularity),
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function formatDateRange(
|
|
99
|
+
value: DateRangeParts,
|
|
100
|
+
granularity: DateGranularity = 'day',
|
|
101
|
+
): DateRangeValue | null {
|
|
102
|
+
if (!value.start && !value.end) return null
|
|
103
|
+
return {
|
|
104
|
+
start: value.start ? formatDateValue(value.start, granularity) : null,
|
|
105
|
+
end: value.end ? formatDateValue(value.end, granularity) : null,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function toDateTime(value: DateValue) {
|
|
110
|
+
return new CalendarDateTime(value.year, value.month, value.day)
|
|
111
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const INTERACTIVE = 'button, a, input, textarea, select, [contenteditable], [role="button"]'
|
|
2
|
+
const CONTROL = 'input:not([type="hidden"]), textarea'
|
|
3
|
+
|
|
4
|
+
function controlOf(node: Element) {
|
|
5
|
+
const control = node.matches(CONTROL) ? node : node.querySelector(CONTROL)
|
|
6
|
+
return control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement
|
|
7
|
+
? control
|
|
8
|
+
: null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function focusFieldFrom(root: HTMLElement, target: HTMLElement) {
|
|
12
|
+
if (target.closest(INTERACTIVE)) return null
|
|
13
|
+
const segments = Array.from(root.children)
|
|
14
|
+
const from = segments.findIndex(segment => segment.contains(target))
|
|
15
|
+
const own = from >= 0 ? controlOf(segments[from]!) : null
|
|
16
|
+
if (own && !own.disabled) {
|
|
17
|
+
own.focus()
|
|
18
|
+
return own
|
|
19
|
+
}
|
|
20
|
+
const after = segments.slice(from + 1)
|
|
21
|
+
const before = segments.slice(0, Math.max(from, 0)).reverse()
|
|
22
|
+
for (const [list, caret] of [
|
|
23
|
+
[after, 'start'],
|
|
24
|
+
[before, 'end'],
|
|
25
|
+
] as const) {
|
|
26
|
+
for (const segment of list) {
|
|
27
|
+
const control = controlOf(segment)
|
|
28
|
+
if (!control || control.disabled) continue
|
|
29
|
+
control.focus()
|
|
30
|
+
const at = caret === 'start' ? 0 : control.value.length
|
|
31
|
+
control.setSelectionRange(at, at)
|
|
32
|
+
return control
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export type FileUploadReason = 'type' | 'size' | 'count'
|
|
2
|
+
|
|
3
|
+
export interface FileUploadRejection {
|
|
4
|
+
file: File
|
|
5
|
+
reason: FileUploadReason
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Rules {
|
|
9
|
+
accept?: string
|
|
10
|
+
maxSize?: number
|
|
11
|
+
maxFiles?: number
|
|
12
|
+
multiple?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function matchesAccept(file: File, accept: string | undefined) {
|
|
16
|
+
if (!accept) return true
|
|
17
|
+
const name = file.name.toLowerCase()
|
|
18
|
+
const type = file.type.toLowerCase()
|
|
19
|
+
return accept
|
|
20
|
+
.split(',')
|
|
21
|
+
.map(rule => rule.trim().toLowerCase())
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.some(rule => {
|
|
24
|
+
if (rule.startsWith('.')) return name.endsWith(rule)
|
|
25
|
+
if (rule.endsWith('/*')) return type.startsWith(rule.slice(0, -1))
|
|
26
|
+
return type === rule
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function sameFile(a: File, b: File) {
|
|
31
|
+
return a.name === b.name && a.size === b.size && a.lastModified === b.lastModified
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function selectFiles(current: File[], incoming: File[], rules: Rules) {
|
|
35
|
+
const rejected: FileUploadRejection[] = []
|
|
36
|
+
const next = rules.multiple ? [...current] : current.slice(0, 1)
|
|
37
|
+
for (const file of incoming) {
|
|
38
|
+
if (!matchesAccept(file, rules.accept)) {
|
|
39
|
+
rejected.push({ file, reason: 'type' })
|
|
40
|
+
continue
|
|
41
|
+
}
|
|
42
|
+
if (rules.maxSize !== undefined && file.size > rules.maxSize) {
|
|
43
|
+
rejected.push({ file, reason: 'size' })
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
if (next.some(existing => sameFile(existing, file))) continue
|
|
47
|
+
if (!rules.multiple) {
|
|
48
|
+
next.splice(0, next.length, file)
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
if (rules.maxFiles !== undefined && next.length >= rules.maxFiles) {
|
|
52
|
+
rejected.push({ file, reason: 'count' })
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
next.push(file)
|
|
56
|
+
}
|
|
57
|
+
return { next, rejected }
|
|
58
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const UNITS = ['byte', 'kilobyte', 'megabyte', 'gigabyte'] as const
|
|
2
|
+
|
|
3
|
+
export function formatSize(tag: string, bytes: number) {
|
|
4
|
+
let value = bytes
|
|
5
|
+
let index = 0
|
|
6
|
+
while (value >= 1024 && index < UNITS.length - 1) {
|
|
7
|
+
value /= 1024
|
|
8
|
+
index += 1
|
|
9
|
+
}
|
|
10
|
+
return new Intl.NumberFormat(tag, {
|
|
11
|
+
style: 'unit',
|
|
12
|
+
unit: UNITS[index],
|
|
13
|
+
unitDisplay: 'narrow',
|
|
14
|
+
maximumFractionDigits: index === 0 ? 0 : 1,
|
|
15
|
+
}).format(value)
|
|
16
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isStandardSchema,
|
|
3
|
+
type FormErrors,
|
|
4
|
+
type FormRules,
|
|
5
|
+
type FormValues,
|
|
6
|
+
type StandardSchemaIssue,
|
|
7
|
+
} from './standard-schema'
|
|
8
|
+
|
|
9
|
+
export const ROOT = ''
|
|
10
|
+
|
|
11
|
+
export function issueKey(issue: StandardSchemaIssue) {
|
|
12
|
+
return (issue.path ?? [])
|
|
13
|
+
.map(part => String(typeof part === 'object' && part !== null ? part.key : part))
|
|
14
|
+
.join('.')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function issuesToErrors(issues: ReadonlyArray<StandardSchemaIssue>): FormErrors {
|
|
18
|
+
const errors: FormErrors = {}
|
|
19
|
+
for (const issue of issues) {
|
|
20
|
+
const key = issueKey(issue)
|
|
21
|
+
if (!(key in errors)) errors[key] = issue.message
|
|
22
|
+
}
|
|
23
|
+
return errors
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function readPath(values: FormValues, key: string): unknown {
|
|
27
|
+
return key
|
|
28
|
+
.split('.')
|
|
29
|
+
.reduce<unknown>(
|
|
30
|
+
(current, part) =>
|
|
31
|
+
current && typeof current === 'object'
|
|
32
|
+
? (current as Record<string, unknown>)[part]
|
|
33
|
+
: undefined,
|
|
34
|
+
values,
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function runRules(
|
|
39
|
+
rules: FormRules | undefined,
|
|
40
|
+
values: FormValues,
|
|
41
|
+
): Promise<FormErrors> {
|
|
42
|
+
if (!rules) return {}
|
|
43
|
+
if (isStandardSchema(rules)) {
|
|
44
|
+
const result = await rules['~standard'].validate(values)
|
|
45
|
+
return result.issues ? issuesToErrors(result.issues) : {}
|
|
46
|
+
}
|
|
47
|
+
return await rules(values)
|
|
48
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const FOCUSABLE = 'input,select,textarea,button,[tabindex],[contenteditable="true"]'
|
|
2
|
+
|
|
3
|
+
export function focusFirstInvalid(root: HTMLElement) {
|
|
4
|
+
const invalid = root.querySelector<HTMLElement>('[aria-invalid="true"]')
|
|
5
|
+
if (!invalid) return
|
|
6
|
+
const target = invalid.matches(FOCUSABLE)
|
|
7
|
+
? invalid
|
|
8
|
+
: invalid.querySelector<HTMLElement>(FOCUSABLE)
|
|
9
|
+
target?.focus()
|
|
10
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface StandardSchemaIssue {
|
|
2
|
+
message: string
|
|
3
|
+
path?: ReadonlyArray<PropertyKey | { key: PropertyKey }>
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface StandardSchemaResult {
|
|
7
|
+
value?: unknown
|
|
8
|
+
issues?: ReadonlyArray<StandardSchemaIssue>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface StandardSchema {
|
|
12
|
+
'~standard': {
|
|
13
|
+
version: 1
|
|
14
|
+
vendor: string
|
|
15
|
+
validate: (value: unknown) => StandardSchemaResult | Promise<StandardSchemaResult>
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type FormValues = Record<string, unknown>
|
|
20
|
+
export type FormErrors = Record<string, string>
|
|
21
|
+
export type FormValidator = (values: FormValues) => FormErrors | Promise<FormErrors>
|
|
22
|
+
export type FormRules = StandardSchema | FormValidator
|
|
23
|
+
|
|
24
|
+
export function isStandardSchema(rules: FormRules): rules is StandardSchema {
|
|
25
|
+
return typeof rules === 'object' && rules !== null && '~standard' in rules
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function isPlain(value: unknown): value is Record<string, unknown> {
|
|
2
|
+
return Object.prototype.toString.call(value) === '[object Object]'
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function snapshot(value: unknown): unknown {
|
|
6
|
+
if (Array.isArray(value)) return value.map(snapshot)
|
|
7
|
+
if (isPlain(value)) {
|
|
8
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshot(item)]))
|
|
9
|
+
}
|
|
10
|
+
return value
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function same(a: unknown, b: unknown): boolean {
|
|
14
|
+
if (a === b) return true
|
|
15
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
16
|
+
return a.length === b.length && a.every((item, index) => same(item, b[index]))
|
|
17
|
+
}
|
|
18
|
+
if (isPlain(a) && isPlain(b)) {
|
|
19
|
+
const keys = Object.keys(a)
|
|
20
|
+
return keys.length === Object.keys(b).length && keys.every(key => same(a[key], b[key]))
|
|
21
|
+
}
|
|
22
|
+
return false
|
|
23
|
+
}
|