@kouji-ui/core 0.1.1 → 0.1.2
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/fesm2022/kouji-ui-core.mjs +26789 -0
- package/fesm2022/kouji-ui-core.mjs.map +1 -0
- package/package.json +5 -6
- package/types/kouji-ui-core.d.ts +13545 -0
- package/.turbo/turbo-build.log +0 -30
- package/CHANGELOG.md +0 -190
- package/ng-package.json +0 -11
- package/src/a11y/.gitkeep +0 -0
- package/src/a11y/aria-describedby.spec.ts +0 -55
- package/src/a11y/aria-describedby.ts +0 -37
- package/src/a11y/aria-labelledby.spec.ts +0 -55
- package/src/a11y/aria-labelledby.ts +0 -38
- package/src/a11y/focus-trap.spec.ts +0 -86
- package/src/a11y/focus-trap.ts +0 -72
- package/src/a11y/index.ts +0 -10
- package/src/a11y/live-region.spec.ts +0 -58
- package/src/a11y/live-region.ts +0 -50
- package/src/a11y/roving-tabindex.spec.ts +0 -201
- package/src/a11y/roving-tabindex.ts +0 -153
- package/src/a11y/visually-hidden.spec.ts +0 -34
- package/src/a11y/visually-hidden.ts +0 -26
- package/src/accordion/accordion.context.ts +0 -44
- package/src/accordion/accordion.spec.ts +0 -242
- package/src/accordion/accordion.ts +0 -401
- package/src/accordion/index.ts +0 -8
- package/src/alert/alert.context.ts +0 -28
- package/src/alert/alert.spec.ts +0 -217
- package/src/alert/alert.ts +0 -417
- package/src/alert/config.ts +0 -46
- package/src/alert/index.ts +0 -19
- package/src/avatar/avatar-group.context.ts +0 -45
- package/src/avatar/avatar-group.spec.ts +0 -358
- package/src/avatar/avatar-group.ts +0 -259
- package/src/avatar/avatar.spec.ts +0 -18
- package/src/avatar/avatar.ts +0 -39
- package/src/avatar/index.ts +0 -11
- package/src/badge/badge.spec.ts +0 -28
- package/src/badge/badge.ts +0 -35
- package/src/badge/index.ts +0 -1
- package/src/breadcrumb/breadcrumb-current.ts +0 -38
- package/src/breadcrumb/breadcrumb-ellipsis.ts +0 -71
- package/src/breadcrumb/breadcrumb-item.ts +0 -41
- package/src/breadcrumb/breadcrumb-link.ts +0 -44
- package/src/breadcrumb/breadcrumb-list.ts +0 -42
- package/src/breadcrumb/breadcrumb-separator.ts +0 -45
- package/src/breadcrumb/breadcrumb.context.ts +0 -45
- package/src/breadcrumb/breadcrumb.spec.ts +0 -354
- package/src/breadcrumb/breadcrumb.ts +0 -239
- package/src/breadcrumb/config.ts +0 -84
- package/src/breadcrumb/index.ts +0 -18
- package/src/button/_examples/button.example.ts +0 -71
- package/src/button/_examples/button.finance.example.ts +0 -83
- package/src/button/_examples/button.retro.example.ts +0 -91
- package/src/button/_examples/button.sizes.example.ts +0 -60
- package/src/button/_examples/index.ts +0 -6
- package/src/button/button.spec.ts +0 -163
- package/src/button/button.ts +0 -142
- package/src/button/config.spec.ts +0 -33
- package/src/button/config.ts +0 -45
- package/src/button/index.ts +0 -2
- package/src/button-group/button-group.context.ts +0 -28
- package/src/button-group/button-group.spec.ts +0 -99
- package/src/button-group/button-group.ts +0 -99
- package/src/button-group/index.ts +0 -2
- package/src/calendar/calendar-day.ts +0 -102
- package/src/calendar/calendar-grid.ts +0 -90
- package/src/calendar/calendar-header.ts +0 -65
- package/src/calendar/calendar.context.ts +0 -53
- package/src/calendar/calendar.spec.ts +0 -225
- package/src/calendar/calendar.ts +0 -233
- package/src/calendar/date-utils.ts +0 -225
- package/src/calendar/index.ts +0 -28
- package/src/carousel/carousel.context.ts +0 -81
- package/src/carousel/carousel.spec.ts +0 -337
- package/src/carousel/carousel.ts +0 -919
- package/src/carousel/index.ts +0 -22
- package/src/cascade-select/cascade-select-option.ts +0 -205
- package/src/cascade-select/cascade-select-panel.ts +0 -106
- package/src/cascade-select/cascade-select-root.ts +0 -265
- package/src/cascade-select/cascade-select-sub-panel.ts +0 -168
- package/src/cascade-select/cascade-select-trigger.ts +0 -44
- package/src/cascade-select/cascade-select.context.ts +0 -71
- package/src/cascade-select/cascade-select.spec.ts +0 -241
- package/src/cascade-select/cascade-select.ts +0 -5
- package/src/cascade-select/index.ts +0 -11
- package/src/chart/chart.spec.ts +0 -27
- package/src/chart/chart.ts +0 -52
- package/src/chart/index.ts +0 -1
- package/src/chat/chat-avatar.ts +0 -31
- package/src/chat/chat-bubble.ts +0 -49
- package/src/chat/chat-footer.ts +0 -67
- package/src/chat/chat-header.ts +0 -41
- package/src/chat/chat-log.ts +0 -43
- package/src/chat/chat.context.ts +0 -64
- package/src/chat/chat.spec.ts +0 -341
- package/src/chat/chat.ts +0 -191
- package/src/chat/config.ts +0 -53
- package/src/chat/index.ts +0 -21
- package/src/checkbox/checkbox.spec.ts +0 -35
- package/src/checkbox/checkbox.ts +0 -89
- package/src/checkbox/index.ts +0 -1
- package/src/color-picker/color-picker.context.ts +0 -74
- package/src/color-picker/color-picker.spec.ts +0 -241
- package/src/color-picker/color-picker.ts +0 -698
- package/src/color-picker/color-picker.utils.ts +0 -140
- package/src/color-picker/index.ts +0 -28
- package/src/combobox/combobox-input.ts +0 -143
- package/src/combobox/combobox-listbox.ts +0 -49
- package/src/combobox/combobox-option.ts +0 -43
- package/src/combobox/combobox-root.ts +0 -281
- package/src/combobox/combobox.spec.ts +0 -75
- package/src/combobox/combobox.ts +0 -4
- package/src/combobox/index.ts +0 -4
- package/src/command-palette/command-empty.ts +0 -36
- package/src/command-palette/command-group.ts +0 -21
- package/src/command-palette/command-input.ts +0 -70
- package/src/command-palette/command-item.ts +0 -60
- package/src/command-palette/command-list.ts +0 -25
- package/src/command-palette/command-palette-dialog.ts +0 -74
- package/src/command-palette/command-palette-trigger.ts +0 -64
- package/src/command-palette/command-palette.filters.ts +0 -53
- package/src/command-palette/command-palette.spec.ts +0 -349
- package/src/command-palette/command-palette.ts +0 -204
- package/src/command-palette/command-separator.ts +0 -18
- package/src/command-palette/index.ts +0 -15
- package/src/confirm-popup/confirm-popup-action.ts +0 -39
- package/src/confirm-popup/confirm-popup-cancel.ts +0 -38
- package/src/confirm-popup/confirm-popup-content.ts +0 -113
- package/src/confirm-popup/confirm-popup-message.ts +0 -36
- package/src/confirm-popup/confirm-popup-trigger.ts +0 -31
- package/src/confirm-popup/confirm-popup.context.ts +0 -41
- package/src/confirm-popup/confirm-popup.spec.ts +0 -337
- package/src/confirm-popup/confirm-popup.ts +0 -109
- package/src/confirm-popup/index.ts +0 -12
- package/src/date-picker/date-picker-calendar.ts +0 -65
- package/src/date-picker/date-picker-trigger.ts +0 -215
- package/src/date-picker/date-picker.context.ts +0 -50
- package/src/date-picker/date-picker.spec.ts +0 -117
- package/src/date-picker/date-picker.ts +0 -127
- package/src/date-picker/index.ts +0 -7
- package/src/dialog/_examples/dialog.confirm.example.ts +0 -145
- package/src/dialog/_examples/dialog.example.ts +0 -106
- package/src/dialog/_examples/dialog.finance.example.ts +0 -121
- package/src/dialog/_examples/dialog.retro.example.ts +0 -126
- package/src/dialog/_examples/index.ts +0 -6
- package/src/dialog/dialog.ref.ts +0 -42
- package/src/dialog/dialog.service.ts +0 -66
- package/src/dialog/dialog.spec.ts +0 -37
- package/src/dialog/dialog.ts +0 -26
- package/src/dialog/index.ts +0 -3
- package/src/divider/divider.spec.ts +0 -223
- package/src/divider/divider.ts +0 -137
- package/src/divider/index.ts +0 -5
- package/src/drawer/drawer.ref.ts +0 -63
- package/src/drawer/drawer.service.ts +0 -106
- package/src/drawer/drawer.spec.ts +0 -117
- package/src/drawer/drawer.ts +0 -122
- package/src/drawer/index.ts +0 -10
- package/src/dropdown-menu/dropdown-menu-content.ts +0 -258
- package/src/dropdown-menu/dropdown-menu-group.ts +0 -31
- package/src/dropdown-menu/dropdown-menu-item.ts +0 -51
- package/src/dropdown-menu/dropdown-menu-label.ts +0 -41
- package/src/dropdown-menu/dropdown-menu-separator.ts +0 -27
- package/src/dropdown-menu/dropdown-menu-trigger.ts +0 -140
- package/src/dropdown-menu/dropdown-menu.spec.ts +0 -265
- package/src/dropdown-menu/dropdown-menu.ts +0 -60
- package/src/dropdown-menu/index.ts +0 -15
- package/src/example-components.ts +0 -42
- package/src/field/field-error.ts +0 -49
- package/src/field/field-group.ts +0 -39
- package/src/field/field-help.ts +0 -47
- package/src/field/field-label.ts +0 -30
- package/src/field/field.context.ts +0 -28
- package/src/field/field.spec.ts +0 -179
- package/src/field/field.ts +0 -121
- package/src/field/index.ts +0 -6
- package/src/file-upload/file-upload.context.ts +0 -89
- package/src/file-upload/file-upload.spec.ts +0 -290
- package/src/file-upload/file-upload.ts +0 -639
- package/src/file-upload/file-upload.types.ts +0 -59
- package/src/file-upload/index.ts +0 -23
- package/src/form/form-error-summary.ts +0 -87
- package/src/form/form-field.context.ts +0 -3
- package/src/form/form-field.spec.ts +0 -25
- package/src/form/form-field.ts +0 -52
- package/src/form/form.context.ts +0 -53
- package/src/form/form.spec.ts +0 -162
- package/src/form/form.ts +0 -326
- package/src/form/index.ts +0 -11
- package/src/icon/E2E.md +0 -14
- package/src/icon/icon.directive.spec.ts +0 -198
- package/src/icon/icon.directive.ts +0 -113
- package/src/icon/icon.mode.spec.ts +0 -29
- package/src/icon/icon.mode.ts +0 -23
- package/src/icon/icon.providers.spec.ts +0 -63
- package/src/icon/icon.providers.ts +0 -47
- package/src/icon/icon.resolver.spec.ts +0 -96
- package/src/icon/icon.resolver.ts +0 -49
- package/src/icon/icon.tokens.ts +0 -88
- package/src/icon/icon.types.ts +0 -48
- package/src/icon/index.ts +0 -21
- package/src/input/index.ts +0 -1
- package/src/input/input.spec.ts +0 -43
- package/src/input/input.ts +0 -89
- package/src/input-group/index.ts +0 -3
- package/src/input-group/input-group-addon.ts +0 -92
- package/src/input-group/input-group.context.ts +0 -27
- package/src/input-group/input-group.spec.ts +0 -186
- package/src/input-group/input-group.ts +0 -136
- package/src/input-mask/index.ts +0 -11
- package/src/input-mask/input-mask.compile.ts +0 -69
- package/src/input-mask/input-mask.engine.ts +0 -376
- package/src/input-mask/input-mask.presets.ts +0 -24
- package/src/input-mask/input-mask.spec.ts +0 -304
- package/src/input-mask/input-mask.tokens.ts +0 -49
- package/src/input-mask/input-mask.ts +0 -280
- package/src/input-otp/index.ts +0 -2
- package/src/input-otp/input-otp.context.ts +0 -41
- package/src/input-otp/input-otp.spec.ts +0 -308
- package/src/input-otp/input-otp.ts +0 -470
- package/src/kbd/index.ts +0 -1
- package/src/kbd/kbd.spec.ts +0 -127
- package/src/kbd/kbd.ts +0 -132
- package/src/link/config.ts +0 -44
- package/src/link/index.ts +0 -2
- package/src/link/link.spec.ts +0 -246
- package/src/link/link.ts +0 -226
- package/src/list/index.ts +0 -11
- package/src/list/list.spec.ts +0 -237
- package/src/list/list.ts +0 -277
- package/src/menubar/index.ts +0 -7
- package/src/menubar/menubar-item.ts +0 -204
- package/src/menubar/menubar.context.ts +0 -43
- package/src/menubar/menubar.spec.ts +0 -433
- package/src/menubar/menubar.ts +0 -309
- package/src/number-input/index.ts +0 -4
- package/src/number-input/number-input-group.ts +0 -64
- package/src/number-input/number-input.context.ts +0 -31
- package/src/number-input/number-input.format.ts +0 -148
- package/src/number-input/number-input.spec.ts +0 -170
- package/src/number-input/number-input.ts +0 -457
- package/src/number-input/number-stepper.ts +0 -193
- package/src/overlay-badge/index.ts +0 -7
- package/src/overlay-badge/overlay-badge-content.ts +0 -73
- package/src/overlay-badge/overlay-badge.context.ts +0 -37
- package/src/overlay-badge/overlay-badge.spec.ts +0 -220
- package/src/overlay-badge/overlay-badge.ts +0 -128
- package/src/pagination/config.ts +0 -82
- package/src/pagination/index.ts +0 -19
- package/src/pagination/page-tokens.ts +0 -78
- package/src/pagination/pagination-ellipsis.ts +0 -69
- package/src/pagination/pagination-first.ts +0 -84
- package/src/pagination/pagination-info.ts +0 -70
- package/src/pagination/pagination-item.ts +0 -81
- package/src/pagination/pagination-last.ts +0 -85
- package/src/pagination/pagination-next.ts +0 -86
- package/src/pagination/pagination-previous.ts +0 -90
- package/src/pagination/pagination.context.ts +0 -52
- package/src/pagination/pagination.spec.ts +0 -388
- package/src/pagination/pagination.ts +0 -288
- package/src/password-input/index.ts +0 -15
- package/src/password-input/password-input.context.ts +0 -65
- package/src/password-input/password-input.scorer.ts +0 -34
- package/src/password-input/password-input.spec.ts +0 -274
- package/src/password-input/password-input.ts +0 -488
- package/src/popover/_examples/index.ts +0 -5
- package/src/popover/_examples/popover.example.ts +0 -92
- package/src/popover/_examples/popover.finance.example.ts +0 -106
- package/src/popover/_examples/popover.retro.example.ts +0 -103
- package/src/popover/index.ts +0 -5
- package/src/popover/popover-arrow.ts +0 -30
- package/src/popover/popover-close.ts +0 -36
- package/src/popover/popover-content.ts +0 -41
- package/src/popover/popover-title.ts +0 -39
- package/src/popover/popover-trigger.ts +0 -40
- package/src/popover/popover.spec.ts +0 -59
- package/src/popover/popover.ts +0 -5
- package/src/presets/bind-presets.spec.ts +0 -50
- package/src/presets/bind-presets.ts +0 -43
- package/src/presets/index.ts +0 -3
- package/src/presets/size.spec.ts +0 -67
- package/src/presets/size.ts +0 -59
- package/src/presets/variant.spec.ts +0 -72
- package/src/presets/variant.ts +0 -62
- package/src/primitives/.gitkeep +0 -0
- package/src/primitives/directionality/directionality.spec.ts +0 -112
- package/src/primitives/directionality/directionality.ts +0 -89
- package/src/primitives/directionality/index.ts +0 -1
- package/src/primitives/forms/form-control.spec.ts +0 -67
- package/src/primitives/forms/form-control.ts +0 -94
- package/src/primitives/forms/index.ts +0 -1
- package/src/primitives/index.ts +0 -6
- package/src/primitives/interaction/disabled.spec.ts +0 -47
- package/src/primitives/interaction/disabled.ts +0 -31
- package/src/primitives/interaction/focus-ring.spec.ts +0 -62
- package/src/primitives/interaction/focus-ring.ts +0 -59
- package/src/primitives/interaction/index.ts +0 -2
- package/src/primitives/list/filterable-list.spec.ts +0 -114
- package/src/primitives/list/filterable-list.ts +0 -126
- package/src/primitives/list/group.spec.ts +0 -99
- package/src/primitives/list/group.ts +0 -139
- package/src/primitives/list/index.ts +0 -8
- package/src/primitives/list/inject-helpers.ts +0 -8
- package/src/primitives/list/item.spec.ts +0 -173
- package/src/primitives/list/item.ts +0 -222
- package/src/primitives/list/navigator.spec.ts +0 -286
- package/src/primitives/list/navigator.ts +0 -238
- package/src/primitives/list/selection.spec.ts +0 -214
- package/src/primitives/list/selection.ts +0 -339
- package/src/primitives/list/tokens.ts +0 -106
- package/src/primitives/list/type-ahead.spec.ts +0 -58
- package/src/primitives/list/type-ahead.ts +0 -46
- package/src/primitives/overlay/backdrop.spec.ts +0 -54
- package/src/primitives/overlay/backdrop.ts +0 -31
- package/src/primitives/overlay/builder.spec.ts +0 -38
- package/src/primitives/overlay/builder.ts +0 -151
- package/src/primitives/overlay/container.ts +0 -42
- package/src/primitives/overlay/context.ts +0 -14
- package/src/primitives/overlay/controller.spec.ts +0 -86
- package/src/primitives/overlay/controller.ts +0 -190
- package/src/primitives/overlay/id.spec.ts +0 -24
- package/src/primitives/overlay/id.ts +0 -17
- package/src/primitives/overlay/index.ts +0 -18
- package/src/primitives/overlay/overlay.css +0 -42
- package/src/primitives/overlay/panel.spec.ts +0 -52
- package/src/primitives/overlay/panel.ts +0 -102
- package/src/primitives/overlay/stack.spec.ts +0 -55
- package/src/primitives/overlay/stack.ts +0 -113
- package/src/primitives/overlay/strategies/backdrop/blurred.spec.ts +0 -11
- package/src/primitives/overlay/strategies/backdrop/blurred.ts +0 -5
- package/src/primitives/overlay/strategies/backdrop/none.spec.ts +0 -10
- package/src/primitives/overlay/strategies/backdrop/none.ts +0 -9
- package/src/primitives/overlay/strategies/backdrop/solid.spec.ts +0 -18
- package/src/primitives/overlay/strategies/backdrop/solid.ts +0 -23
- package/src/primitives/overlay/strategies/focus-trap/inert-based.spec.ts +0 -28
- package/src/primitives/overlay/strategies/focus-trap/inert-based.ts +0 -38
- package/src/primitives/overlay/strategies/focus-trap/no-trap.spec.ts +0 -9
- package/src/primitives/overlay/strategies/focus-trap/no-trap.ts +0 -8
- package/src/primitives/overlay/strategies/focus-trap/tab-cycle.spec.ts +0 -49
- package/src/primitives/overlay/strategies/focus-trap/tab-cycle.ts +0 -85
- package/src/primitives/overlay/strategies/index.ts +0 -34
- package/src/primitives/overlay/strategies/live-announcer/_announce.ts +0 -35
- package/src/primitives/overlay/strategies/live-announcer/assertive.spec.ts +0 -21
- package/src/primitives/overlay/strategies/live-announcer/assertive.ts +0 -11
- package/src/primitives/overlay/strategies/live-announcer/polite.spec.ts +0 -21
- package/src/primitives/overlay/strategies/live-announcer/polite.ts +0 -11
- package/src/primitives/overlay/strategies/live-announcer/silent.spec.ts +0 -12
- package/src/primitives/overlay/strategies/live-announcer/silent.ts +0 -5
- package/src/primitives/overlay/strategies/mount/body-portal.spec.ts +0 -40
- package/src/primitives/overlay/strategies/mount/body-portal.ts +0 -91
- package/src/primitives/overlay/strategies/mount/in-container.spec.ts +0 -43
- package/src/primitives/overlay/strategies/mount/in-container.ts +0 -39
- package/src/primitives/overlay/strategies/mount/in-place.spec.ts +0 -40
- package/src/primitives/overlay/strategies/mount/in-place.ts +0 -20
- package/src/primitives/overlay/strategies/position/anchored-to.spec.ts +0 -56
- package/src/primitives/overlay/strategies/position/anchored-to.ts +0 -248
- package/src/primitives/overlay/strategies/position/corner.spec.ts +0 -36
- package/src/primitives/overlay/strategies/position/corner.ts +0 -33
- package/src/primitives/overlay/strategies/position/edge-sheet.spec.ts +0 -32
- package/src/primitives/overlay/strategies/position/edge-sheet.ts +0 -36
- package/src/primitives/overlay/strategies/position/in-place-sibling.spec.ts +0 -25
- package/src/primitives/overlay/strategies/position/in-place-sibling.ts +0 -13
- package/src/primitives/overlay/strategies/position/point-at.spec.ts +0 -40
- package/src/primitives/overlay/strategies/position/point-at.ts +0 -34
- package/src/primitives/overlay/strategies/position/viewport-centered.spec.ts +0 -31
- package/src/primitives/overlay/strategies/position/viewport-centered.ts +0 -31
- package/src/primitives/overlay/strategies/scroll-lock/css-clip.spec.ts +0 -15
- package/src/primitives/overlay/strategies/scroll-lock/css-clip.ts +0 -39
- package/src/primitives/overlay/strategies/scroll-lock/html-overflow.spec.ts +0 -21
- package/src/primitives/overlay/strategies/scroll-lock/html-overflow.ts +0 -44
- package/src/primitives/overlay/strategies/scroll-lock/none.spec.ts +0 -9
- package/src/primitives/overlay/strategies/scroll-lock/none.ts +0 -5
- package/src/primitives/overlay/strategies/trigger-event/on-click.spec.ts +0 -32
- package/src/primitives/overlay/strategies/trigger-event/on-click.ts +0 -28
- package/src/primitives/overlay/strategies/trigger-event/on-context-menu.spec.ts +0 -45
- package/src/primitives/overlay/strategies/trigger-event/on-context-menu.ts +0 -70
- package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.spec.ts +0 -35
- package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.ts +0 -34
- package/src/primitives/overlay/strategies/trigger-event/on-focus.spec.ts +0 -64
- package/src/primitives/overlay/strategies/trigger-event/on-focus.ts +0 -37
- package/src/primitives/overlay/strategies/trigger-event/on-hotkey.spec.ts +0 -37
- package/src/primitives/overlay/strategies/trigger-event/on-hotkey.ts +0 -59
- package/src/primitives/overlay/strategies/trigger-event/on-hover.spec.ts +0 -34
- package/src/primitives/overlay/strategies/trigger-event/on-hover.ts +0 -86
- package/src/primitives/overlay/strategies/trigger-event/programmatic.spec.ts +0 -16
- package/src/primitives/overlay/strategies/trigger-event/programmatic.ts +0 -12
- package/src/primitives/overlay/tokens.ts +0 -54
- package/src/primitives/overlay/trigger.spec.ts +0 -103
- package/src/primitives/overlay/trigger.ts +0 -75
- package/src/primitives/overlay/types.ts +0 -24
- package/src/primitives/overlay/wrapper.ts +0 -50
- package/src/primitives/signals/deep-signal.ts +0 -109
- package/src/primitives/signals/index.ts +0 -1
- package/src/progress-bar/config.ts +0 -48
- package/src/progress-bar/index.ts +0 -12
- package/src/progress-bar/progress-bar-fill.ts +0 -37
- package/src/progress-bar/progress-bar.context.ts +0 -34
- package/src/progress-bar/progress-bar.spec.ts +0 -423
- package/src/progress-bar/progress-bar.ts +0 -217
- package/src/public-api.ts +0 -84
- package/src/radio/index.ts +0 -2
- package/src/radio/radio.context.ts +0 -3
- package/src/radio/radio.spec.ts +0 -36
- package/src/radio/radio.ts +0 -66
- package/src/select/index.ts +0 -4
- package/src/select/select-content.ts +0 -69
- package/src/select/select-option.ts +0 -35
- package/src/select/select-root.ts +0 -129
- package/src/select/select-trigger.ts +0 -93
- package/src/select/select.spec.ts +0 -138
- package/src/select/select.ts +0 -4
- package/src/skeleton/index.ts +0 -5
- package/src/skeleton/skeleton.spec.ts +0 -115
- package/src/skeleton/skeleton.ts +0 -56
- package/src/slider/index.ts +0 -10
- package/src/slider/slider-range.ts +0 -49
- package/src/slider/slider-thumb.ts +0 -335
- package/src/slider/slider-track.ts +0 -70
- package/src/slider/slider.context.ts +0 -79
- package/src/slider/slider.geometry.ts +0 -73
- package/src/slider/slider.spec.ts +0 -216
- package/src/slider/slider.ts +0 -443
- package/src/speed-dial/index.ts +0 -10
- package/src/speed-dial/speed-dial-action.ts +0 -40
- package/src/speed-dial/speed-dial-actions.ts +0 -31
- package/src/speed-dial/speed-dial-trigger.ts +0 -55
- package/src/speed-dial/speed-dial.context.ts +0 -36
- package/src/speed-dial/speed-dial.spec.ts +0 -143
- package/src/speed-dial/speed-dial.ts +0 -127
- package/src/spinner/config.ts +0 -48
- package/src/spinner/index.ts +0 -8
- package/src/spinner/spinner.spec.ts +0 -262
- package/src/spinner/spinner.ts +0 -129
- package/src/stepper/index.ts +0 -15
- package/src/stepper/stepper.context.ts +0 -63
- package/src/stepper/stepper.spec.ts +0 -403
- package/src/stepper/stepper.ts +0 -544
- package/src/styles/docs-themes.css +0 -82
- package/src/styles.css +0 -17
- package/src/table/column-helpers.spec.ts +0 -74
- package/src/table/column-helpers.ts +0 -68
- package/src/table/filter-fns.ts +0 -230
- package/src/table/filter-models.spec.ts +0 -240
- package/src/table/filter-models.ts +0 -124
- package/src/table/filter-params.ts +0 -90
- package/src/table/grid-api-impl.ts +0 -321
- package/src/table/grid-api.spec.ts +0 -178
- package/src/table/grid-api.ts +0 -285
- package/src/table/index.ts +0 -73
- package/src/table/table-cell.spec.ts +0 -43
- package/src/table/table-cell.ts +0 -38
- package/src/table/table-filter-outlet.ts +0 -120
- package/src/table/table-header.spec.ts +0 -54
- package/src/table/table-header.ts +0 -63
- package/src/table/table-keyboard.spec.ts +0 -68
- package/src/table/table-keyboard.ts +0 -107
- package/src/table/table-resource.spec.ts +0 -37
- package/src/table/table-resource.ts +0 -36
- package/src/table/table-row.spec.ts +0 -54
- package/src/table/table-row.ts +0 -31
- package/src/table/table-storage.spec.ts +0 -67
- package/src/table/table-storage.ts +0 -76
- package/src/table/table.spec.ts +0 -172
- package/src/table/table.ts +0 -281
- package/src/table/table.types.ts +0 -83
- package/src/tabs/index.ts +0 -7
- package/src/tabs/tabs.context.ts +0 -32
- package/src/tabs/tabs.spec.ts +0 -352
- package/src/tabs/tabs.ts +0 -364
- package/src/tag/config.ts +0 -53
- package/src/tag/index.ts +0 -7
- package/src/tag/tag-list.ts +0 -76
- package/src/tag/tag-remove.ts +0 -61
- package/src/tag/tag.context.ts +0 -36
- package/src/tag/tag.spec.ts +0 -240
- package/src/tag/tag.ts +0 -203
- package/src/test-setup.ts +0 -5
- package/src/textarea/config.ts +0 -42
- package/src/textarea/index.ts +0 -8
- package/src/textarea/textarea.spec.ts +0 -176
- package/src/textarea/textarea.ts +0 -235
- package/src/time-picker/index.ts +0 -15
- package/src/time-picker/time-picker-meridiem.ts +0 -123
- package/src/time-picker/time-picker-segment.ts +0 -318
- package/src/time-picker/time-picker.context.ts +0 -38
- package/src/time-picker/time-picker.format.ts +0 -181
- package/src/time-picker/time-picker.spec.ts +0 -189
- package/src/time-picker/time-picker.ts +0 -274
- package/src/toast/_examples/index.ts +0 -5
- package/src/toast/_examples/toast.example.ts +0 -282
- package/src/toast/_examples/toast.finance.example.ts +0 -180
- package/src/toast/_examples/toast.retro.example.ts +0 -161
- package/src/toast/index.ts +0 -28
- package/src/toast/toast.ref.ts +0 -26
- package/src/toast/toast.service.ts +0 -339
- package/src/toast/toast.spec.ts +0 -247
- package/src/toast/toast.strategy.ts +0 -112
- package/src/toast/toast.ts +0 -463
- package/src/toast/toast.types.ts +0 -5
- package/src/toggle/index.ts +0 -1
- package/src/toggle/toggle.spec.ts +0 -24
- package/src/toggle/toggle.ts +0 -48
- package/src/tooltip/_examples/index.ts +0 -6
- package/src/tooltip/_examples/tooltip.example.ts +0 -82
- package/src/tooltip/_examples/tooltip.finance.example.ts +0 -97
- package/src/tooltip/_examples/tooltip.placements.example.ts +0 -83
- package/src/tooltip/_examples/tooltip.retro.example.ts +0 -107
- package/src/tooltip/index.ts +0 -4
- package/src/tooltip/tooltip-arrow.ts +0 -31
- package/src/tooltip/tooltip-content.ts +0 -38
- package/src/tooltip/tooltip-group.ts +0 -32
- package/src/tooltip/tooltip-trigger.ts +0 -47
- package/src/tooltip/tooltip.spec.ts +0 -40
- package/src/tooltip/tooltip.ts +0 -5
- package/src/tree-select/index.ts +0 -12
- package/src/tree-select/tree-select-content.ts +0 -199
- package/src/tree-select/tree-select-node.ts +0 -132
- package/src/tree-select/tree-select-root.ts +0 -272
- package/src/tree-select/tree-select-trigger.ts +0 -90
- package/src/tree-select/tree-select.context.ts +0 -63
- package/src/tree-select/tree-select.spec.ts +0 -433
- package/src/tree-select/tree-select.ts +0 -2
- package/src/typography/blockquote.ts +0 -57
- package/src/typography/code.ts +0 -53
- package/src/typography/index.ts +0 -22
- package/src/typography/lead.ts +0 -49
- package/src/typography/muted.ts +0 -29
- package/src/typography/truncate.ts +0 -99
- package/src/typography/typography.spec.ts +0 -203
- package/tsconfig.lib.json +0 -21
- package/tsconfig.lib.prod.json +0 -17
- package/tsconfig.spec.json +0 -18
- package/vite.config.ts +0 -27
- /package/{src/icon → icon}/icon.css +0 -0
- /package/{src/typography → typography}/prose.css +0 -0
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { kjColumn, kjColumnGroup } from './column-helpers';
|
|
3
|
-
|
|
4
|
-
interface User { id: string; name: string; email: string; age: number; }
|
|
5
|
-
type AnyRec = Record<string, unknown>;
|
|
6
|
-
|
|
7
|
-
describe('kjColumn', () => {
|
|
8
|
-
it('returns a ColumnDef compatible with TanStack', () => {
|
|
9
|
-
const col = kjColumn<User>({ accessorKey: 'name', header: 'Name' });
|
|
10
|
-
expect(col.accessorKey).toBe('name');
|
|
11
|
-
expect(col.header).toBe('Name');
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('hoists kj* knobs into meta.kj', () => {
|
|
15
|
-
const col = kjColumn<User>({
|
|
16
|
-
accessorKey: 'name',
|
|
17
|
-
kjType: 'text',
|
|
18
|
-
kjEditable: true,
|
|
19
|
-
kjPin: 'left',
|
|
20
|
-
});
|
|
21
|
-
expect((col.meta as AnyRec)?.kj).toEqual({
|
|
22
|
-
type: 'text',
|
|
23
|
-
editable: true,
|
|
24
|
-
pin: 'left',
|
|
25
|
-
});
|
|
26
|
-
// top-level kj* fields are stripped — TanStack sees only its native fields.
|
|
27
|
-
expect((col as AnyRec).kjType).toBeUndefined();
|
|
28
|
-
expect((col as AnyRec).kjEditable).toBeUndefined();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('preserves existing meta', () => {
|
|
32
|
-
const col = kjColumn<User>({
|
|
33
|
-
accessorKey: 'name',
|
|
34
|
-
meta: { foo: 'bar' } as AnyRec,
|
|
35
|
-
kjEditable: true,
|
|
36
|
-
});
|
|
37
|
-
expect((col.meta as AnyRec).foo).toBe('bar');
|
|
38
|
-
expect(((col.meta as AnyRec).kj as AnyRec).editable).toBe(true);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('omits meta.kj when no kj* knobs are passed', () => {
|
|
42
|
-
const col = kjColumn<User>({ accessorKey: 'name' });
|
|
43
|
-
expect((col.meta as AnyRec)?.kj).toBeUndefined();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('auto-wires filterFn from kjType so the built-in filter UIs round-trip', () => {
|
|
47
|
-
const text = kjColumn<User>({ accessorKey: 'name', kjType: 'text' });
|
|
48
|
-
const number = kjColumn<User>({ accessorKey: 'age', kjType: 'number' });
|
|
49
|
-
const sel = kjColumn<User>({ accessorKey: 'email', kjType: 'select' });
|
|
50
|
-
expect(typeof (text as AnyRec).filterFn).toBe('function');
|
|
51
|
-
expect(typeof (number as AnyRec).filterFn).toBe('function');
|
|
52
|
-
expect(typeof (sel as AnyRec).filterFn).toBe('function');
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('respects a user-supplied filterFn over the auto-wired default', () => {
|
|
56
|
-
const custom = () => true;
|
|
57
|
-
const col = kjColumn<User>({ accessorKey: 'age', kjType: 'number', filterFn: custom });
|
|
58
|
-
expect((col as AnyRec).filterFn).toBe(custom);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
describe('kjColumnGroup', () => {
|
|
63
|
-
it('returns a group column def with nested columns', () => {
|
|
64
|
-
const grp = kjColumnGroup<User>({
|
|
65
|
-
header: 'Identity',
|
|
66
|
-
columns: [
|
|
67
|
-
kjColumn<User>({ accessorKey: 'name' }),
|
|
68
|
-
kjColumn<User>({ accessorKey: 'email' }),
|
|
69
|
-
],
|
|
70
|
-
});
|
|
71
|
-
expect(grp.header).toBe('Identity');
|
|
72
|
-
expect((grp as AnyRec).columns).toHaveLength(2);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import type { ColumnDef, FilterFn, RowData } from '@tanstack/angular-table';
|
|
2
|
-
import {
|
|
3
|
-
kjDateFilterFn,
|
|
4
|
-
kjNumberFilterFn,
|
|
5
|
-
kjSetFilterFn,
|
|
6
|
-
kjTextFilterFn,
|
|
7
|
-
} from './filter-fns';
|
|
8
|
-
import type { KjColumnDef, KjColumnMeta, KjColumnType } from './table.types';
|
|
9
|
-
|
|
10
|
-
const KJ_KEYS = [
|
|
11
|
-
'kjType', 'kjEditable', 'kjFilterable', 'kjPin', 'kjGroup', 'kjAgg',
|
|
12
|
-
'kjEditor', 'kjFilterUi', 'kjSelectOptions', 'kjExportable', 'kjPersist',
|
|
13
|
-
] as const;
|
|
14
|
-
|
|
15
|
-
/** Auto-wired matcher per `kjType`. Picked up only when the column def
|
|
16
|
-
* doesn't already supply its own `filterFn`. */
|
|
17
|
-
const DEFAULT_FILTER_FNS: Readonly<Record<KjColumnType, FilterFn<unknown>>> = {
|
|
18
|
-
text: kjTextFilterFn as unknown as FilterFn<unknown>,
|
|
19
|
-
number: kjNumberFilterFn as unknown as FilterFn<unknown>,
|
|
20
|
-
date: kjDateFilterFn as unknown as FilterFn<unknown>,
|
|
21
|
-
select: kjSetFilterFn as unknown as FilterFn<unknown>,
|
|
22
|
-
boolean: kjSetFilterFn as unknown as FilterFn<unknown>,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/** Strip leading 'kj' and lowercase first char. */
|
|
26
|
-
function unprefix(k: string): keyof KjColumnMeta {
|
|
27
|
-
return (k.slice(2, 3).toLowerCase() + k.slice(3)) as keyof KjColumnMeta;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Define a column for `<kj-data-table>`. Pass-through for every TanStack
|
|
32
|
-
* `ColumnDef` field; kj-specific top-level knobs (`kjType`, `kjEditable`,
|
|
33
|
-
* `kjPin`, …) are hoisted into `meta.kj` for the wrapper to read.
|
|
34
|
-
*/
|
|
35
|
-
export function kjColumn<TData extends RowData>(def: KjColumnDef<TData>): ColumnDef<TData> {
|
|
36
|
-
const kjMeta: Partial<KjColumnMeta<TData>> = {};
|
|
37
|
-
const rest: Record<string, unknown> = {};
|
|
38
|
-
for (const [k, v] of Object.entries(def)) {
|
|
39
|
-
if ((KJ_KEYS as readonly string[]).includes(k)) {
|
|
40
|
-
if (v !== undefined) kjMeta[unprefix(k)] = v as never;
|
|
41
|
-
} else {
|
|
42
|
-
rest[k] = v;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const existingMeta = (rest['meta'] ?? {}) as Record<string, unknown>;
|
|
46
|
-
const meta = Object.keys(kjMeta).length === 0
|
|
47
|
-
? existingMeta
|
|
48
|
-
: { ...existingMeta, kj: kjMeta };
|
|
49
|
-
|
|
50
|
-
// Auto-wire `filterFn` from `kjType` so columns built with `kjColumn({ ... })`
|
|
51
|
-
// actually understand the structured `KjFilterModel` the built-in filter UIs
|
|
52
|
-
// write. User-supplied `filterFn` always wins.
|
|
53
|
-
if (rest['filterFn'] === undefined && kjMeta.type) {
|
|
54
|
-
const fn = DEFAULT_FILTER_FNS[kjMeta.type as KjColumnType];
|
|
55
|
-
if (fn) rest['filterFn'] = fn as unknown as FilterFn<TData>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return { ...rest, meta } as unknown as ColumnDef<TData>;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** Define a column group (header grouping). Children are `kjColumn()` defs. */
|
|
62
|
-
export function kjColumnGroup<TData extends RowData>(def: {
|
|
63
|
-
id?: string;
|
|
64
|
-
header: ColumnDef<TData>['header'];
|
|
65
|
-
columns: ColumnDef<TData>[];
|
|
66
|
-
}): ColumnDef<TData> {
|
|
67
|
-
return def as unknown as ColumnDef<TData>;
|
|
68
|
-
}
|
package/src/table/filter-fns.ts
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import type { Row } from '@tanstack/angular-table';
|
|
2
|
-
import {
|
|
3
|
-
isKjFilterModel,
|
|
4
|
-
type KjDateFilterModel,
|
|
5
|
-
type KjFilterModel,
|
|
6
|
-
type KjMultiConditionFilterModel,
|
|
7
|
-
type KjNumberFilterModel,
|
|
8
|
-
type KjSetFilterModel,
|
|
9
|
-
type KjTextFilterModel,
|
|
10
|
-
} from './filter-models';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* TanStack `filterFn` for {@link KjTextFilterModel}. Accepts the model as
|
|
14
|
-
* the filter value and dispatches on `model.type`. Tolerates a bare
|
|
15
|
-
* string (legacy "contains" raw value) so users migrating filters one at
|
|
16
|
-
* a time don't have to flip every column simultaneously.
|
|
17
|
-
*
|
|
18
|
-
* Usage:
|
|
19
|
-
* ```ts
|
|
20
|
-
* kjColumn<User>({ accessorKey: 'name', filterFn: kjTextFilterFn })
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export function kjTextFilterFn<TData>(
|
|
24
|
-
row: Row<TData>,
|
|
25
|
-
columnId: string,
|
|
26
|
-
filterValue: unknown,
|
|
27
|
-
): boolean {
|
|
28
|
-
if (filterValue == null || filterValue === '') return true;
|
|
29
|
-
|
|
30
|
-
// Legacy raw-string compatibility — treated as `contains`.
|
|
31
|
-
if (typeof filterValue === 'string') {
|
|
32
|
-
return contains(read(row, columnId), filterValue, /* caseSensitive */ false);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (!isKjFilterModel(filterValue) || filterValue.filterType !== 'text') return true;
|
|
36
|
-
const model = filterValue as KjTextFilterModel;
|
|
37
|
-
const cell = read(row, columnId);
|
|
38
|
-
const cs = model.caseSensitive === true;
|
|
39
|
-
|
|
40
|
-
switch (model.type) {
|
|
41
|
-
case 'blank': return cell == null || cell === '';
|
|
42
|
-
case 'notBlank': return cell != null && cell !== '';
|
|
43
|
-
case 'equals': return text(cell, cs) === text(model.filter ?? '', cs);
|
|
44
|
-
case 'notEquals': return text(cell, cs) !== text(model.filter ?? '', cs);
|
|
45
|
-
case 'contains': return contains(cell, model.filter ?? '', cs);
|
|
46
|
-
case 'notContains': return !contains(cell, model.filter ?? '', cs);
|
|
47
|
-
case 'startsWith': return text(cell, cs).startsWith(text(model.filter ?? '', cs));
|
|
48
|
-
case 'endsWith': return text(cell, cs).endsWith(text(model.filter ?? '', cs));
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* TanStack `filterFn` for {@link KjNumberFilterModel}. Tolerates a bare
|
|
54
|
-
* `[min, max]` tuple as legacy raw value (treated as `inRange`).
|
|
55
|
-
*/
|
|
56
|
-
export function kjNumberFilterFn<TData>(
|
|
57
|
-
row: Row<TData>,
|
|
58
|
-
columnId: string,
|
|
59
|
-
filterValue: unknown,
|
|
60
|
-
): boolean {
|
|
61
|
-
if (filterValue == null) return true;
|
|
62
|
-
|
|
63
|
-
// Legacy `[min, max]` tuple → inRange.
|
|
64
|
-
if (Array.isArray(filterValue)) {
|
|
65
|
-
const [min, max] = filterValue as [number | undefined, number | undefined];
|
|
66
|
-
return inNumberRange(Number(read(row, columnId)), min, max);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!isKjFilterModel(filterValue) || filterValue.filterType !== 'number') return true;
|
|
70
|
-
const model = filterValue as KjNumberFilterModel;
|
|
71
|
-
const cell = Number(read(row, columnId));
|
|
72
|
-
|
|
73
|
-
if (model.type === 'blank') return Number.isNaN(cell);
|
|
74
|
-
if (model.type === 'notBlank') return !Number.isNaN(cell);
|
|
75
|
-
|
|
76
|
-
// `inRange` is the one operator where a missing `filter` is still
|
|
77
|
-
// meaningful — it just leaves the lower bound open. Every other operator
|
|
78
|
-
// needs an explicit `filter`, so we treat its absence as "no filter".
|
|
79
|
-
if (model.type === 'inRange') {
|
|
80
|
-
if (model.filter == null && model.filterTo == null) return true;
|
|
81
|
-
return inNumberRange(cell, model.filter, model.filterTo);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const value = model.filter;
|
|
85
|
-
if (value == null) return true;
|
|
86
|
-
|
|
87
|
-
switch (model.type) {
|
|
88
|
-
case 'equals': return cell === value;
|
|
89
|
-
case 'notEquals': return cell !== value;
|
|
90
|
-
case 'greaterThan': return cell > value;
|
|
91
|
-
case 'greaterThanOrEqual': return cell >= value;
|
|
92
|
-
case 'lessThan': return cell < value;
|
|
93
|
-
case 'lessThanOrEqual': return cell <= value;
|
|
94
|
-
}
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* TanStack `filterFn` for {@link KjDateFilterModel}. Compares ISO date
|
|
100
|
-
* strings as calendar dates (no time component, no TZ math). Tolerates a
|
|
101
|
-
* `[from, to]` tuple of ISO strings as legacy raw value.
|
|
102
|
-
*/
|
|
103
|
-
export function kjDateFilterFn<TData>(
|
|
104
|
-
row: Row<TData>,
|
|
105
|
-
columnId: string,
|
|
106
|
-
filterValue: unknown,
|
|
107
|
-
): boolean {
|
|
108
|
-
if (filterValue == null) return true;
|
|
109
|
-
|
|
110
|
-
if (Array.isArray(filterValue)) {
|
|
111
|
-
const [from, to] = filterValue as [string | undefined, string | undefined];
|
|
112
|
-
return inIsoRange(isoOf(read(row, columnId)), from, to);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (!isKjFilterModel(filterValue) || filterValue.filterType !== 'date') return true;
|
|
116
|
-
const model = filterValue as KjDateFilterModel;
|
|
117
|
-
const cell = isoOf(read(row, columnId));
|
|
118
|
-
|
|
119
|
-
if (model.type === 'blank') return !cell;
|
|
120
|
-
if (model.type === 'notBlank') return !!cell;
|
|
121
|
-
if (!cell) return false;
|
|
122
|
-
|
|
123
|
-
switch (model.type) {
|
|
124
|
-
case 'equals': return cell === model.dateFrom;
|
|
125
|
-
case 'notEquals': return cell !== model.dateFrom;
|
|
126
|
-
case 'greaterThan': return !!model.dateFrom && cell > model.dateFrom;
|
|
127
|
-
case 'lessThan': return !!model.dateFrom && cell < model.dateFrom;
|
|
128
|
-
case 'inRange': return inIsoRange(cell, model.dateFrom, model.dateTo);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* TanStack `filterFn` for {@link KjSetFilterModel}. The row passes if the
|
|
134
|
-
* cell's stringified value matches any selected entry. Tolerates a bare
|
|
135
|
-
* (non-array) value as legacy raw equality.
|
|
136
|
-
*/
|
|
137
|
-
export function kjSetFilterFn<TData>(
|
|
138
|
-
row: Row<TData>,
|
|
139
|
-
columnId: string,
|
|
140
|
-
filterValue: unknown,
|
|
141
|
-
): boolean {
|
|
142
|
-
if (filterValue == null) return true;
|
|
143
|
-
|
|
144
|
-
if (!isKjFilterModel(filterValue)) {
|
|
145
|
-
return Object.is(read(row, columnId), filterValue);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (filterValue.filterType !== 'set') return true;
|
|
149
|
-
const model = filterValue as KjSetFilterModel;
|
|
150
|
-
if (model.values.length === 0) return true;
|
|
151
|
-
const cell = read(row, columnId);
|
|
152
|
-
return model.values.some((v) => Object.is(v, cell));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* TanStack `filterFn` for {@link KjMultiConditionFilterModel}.
|
|
157
|
-
* Recursively delegates each condition to the matching helper based on
|
|
158
|
-
* `condition.filterType`.
|
|
159
|
-
*/
|
|
160
|
-
export function kjMultiFilterFn<TData>(
|
|
161
|
-
row: Row<TData>,
|
|
162
|
-
columnId: string,
|
|
163
|
-
filterValue: unknown,
|
|
164
|
-
): boolean {
|
|
165
|
-
if (!isKjFilterModel(filterValue) || filterValue.filterType !== 'multi') return true;
|
|
166
|
-
const model = filterValue as KjMultiConditionFilterModel;
|
|
167
|
-
const reduce = model.operator === 'AND'
|
|
168
|
-
? model.conditions.every.bind(model.conditions)
|
|
169
|
-
: model.conditions.some.bind(model.conditions);
|
|
170
|
-
return reduce((c) => evaluate(row, columnId, c));
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** Dispatch a single model against the correct typed helper. */
|
|
174
|
-
function evaluate<TData>(
|
|
175
|
-
row: Row<TData>,
|
|
176
|
-
columnId: string,
|
|
177
|
-
model: KjFilterModel,
|
|
178
|
-
): boolean {
|
|
179
|
-
switch (model.filterType) {
|
|
180
|
-
case 'text': return kjTextFilterFn(row, columnId, model);
|
|
181
|
-
case 'number': return kjNumberFilterFn(row, columnId, model);
|
|
182
|
-
case 'date': return kjDateFilterFn(row, columnId, model);
|
|
183
|
-
case 'set': return kjSetFilterFn(row, columnId, model);
|
|
184
|
-
case 'multi': return kjMultiFilterFn(row, columnId, model);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// ── primitives ─────────────────────────────────────────────────────────────
|
|
189
|
-
|
|
190
|
-
function read<TData>(row: Row<TData>, columnId: string): unknown {
|
|
191
|
-
return row.getValue(columnId);
|
|
192
|
-
}
|
|
193
|
-
function text(value: unknown, caseSensitive: boolean): string {
|
|
194
|
-
const s = value == null ? '' : String(value);
|
|
195
|
-
return caseSensitive ? s : s.toLowerCase();
|
|
196
|
-
}
|
|
197
|
-
function contains(cell: unknown, needle: string, caseSensitive: boolean): boolean {
|
|
198
|
-
return text(cell, caseSensitive).includes(text(needle, caseSensitive));
|
|
199
|
-
}
|
|
200
|
-
function inNumberRange(
|
|
201
|
-
cell: number,
|
|
202
|
-
min: number | undefined,
|
|
203
|
-
max: number | undefined,
|
|
204
|
-
): boolean {
|
|
205
|
-
if (Number.isNaN(cell)) return false;
|
|
206
|
-
if (min !== undefined && cell < min) return false;
|
|
207
|
-
if (max !== undefined && cell > max) return false;
|
|
208
|
-
return true;
|
|
209
|
-
}
|
|
210
|
-
function inIsoRange(
|
|
211
|
-
cell: string | undefined,
|
|
212
|
-
from: string | undefined,
|
|
213
|
-
to: string | undefined,
|
|
214
|
-
): boolean {
|
|
215
|
-
if (!cell) return false;
|
|
216
|
-
if (from && cell < from) return false;
|
|
217
|
-
if (to && cell > to) return false;
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
function isoOf(value: unknown): string | undefined {
|
|
221
|
-
if (!value) return undefined;
|
|
222
|
-
if (value instanceof Date) {
|
|
223
|
-
const y = value.getFullYear();
|
|
224
|
-
const m = String(value.getMonth() + 1).padStart(2, '0');
|
|
225
|
-
const d = String(value.getDate()).padStart(2, '0');
|
|
226
|
-
return `${y}-${m}-${d}`;
|
|
227
|
-
}
|
|
228
|
-
if (typeof value === 'string') return value.slice(0, 10);
|
|
229
|
-
return undefined;
|
|
230
|
-
}
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import { Component, signal, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { render } from '@testing-library/angular';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
import { KjTable } from './table';
|
|
5
|
-
import { kjColumn } from './column-helpers';
|
|
6
|
-
import {
|
|
7
|
-
kjTextFilterFn,
|
|
8
|
-
kjNumberFilterFn,
|
|
9
|
-
kjDateFilterFn,
|
|
10
|
-
kjSetFilterFn,
|
|
11
|
-
kjMultiFilterFn,
|
|
12
|
-
} from './filter-fns';
|
|
13
|
-
import type {
|
|
14
|
-
KjDateFilterModel,
|
|
15
|
-
KjMultiConditionFilterModel,
|
|
16
|
-
KjNumberFilterModel,
|
|
17
|
-
KjSetFilterModel,
|
|
18
|
-
KjTextFilterModel,
|
|
19
|
-
} from './filter-models';
|
|
20
|
-
|
|
21
|
-
interface Row {
|
|
22
|
-
id: string;
|
|
23
|
-
name: string;
|
|
24
|
-
age: number;
|
|
25
|
-
joined: string;
|
|
26
|
-
role: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@Component({
|
|
30
|
-
standalone: true,
|
|
31
|
-
imports: [KjTable],
|
|
32
|
-
changeDetection: ChangeDetectionStrategy.Eager,
|
|
33
|
-
template: `<table
|
|
34
|
-
[kjTable]="cols"
|
|
35
|
-
[kjTableData]="data()"
|
|
36
|
-
[kjGetRowId]="getId"
|
|
37
|
-
#t="kjTable"
|
|
38
|
-
></table>`,
|
|
39
|
-
})
|
|
40
|
-
class Host {
|
|
41
|
-
protected readonly cols = [
|
|
42
|
-
kjColumn<Row>({ accessorKey: 'name', header: 'Name', filterFn: kjTextFilterFn }),
|
|
43
|
-
kjColumn<Row>({ accessorKey: 'age', header: 'Age', filterFn: kjNumberFilterFn }),
|
|
44
|
-
kjColumn<Row>({ accessorKey: 'joined', header: 'Joined', filterFn: kjDateFilterFn }),
|
|
45
|
-
kjColumn<Row>({ accessorKey: 'role', header: 'Role', filterFn: kjSetFilterFn }),
|
|
46
|
-
];
|
|
47
|
-
protected readonly data = signal<Row[]>([
|
|
48
|
-
{ id: '1', name: 'Alice', age: 30, joined: '2024-01-15', role: 'admin' },
|
|
49
|
-
{ id: '2', name: 'Bob', age: 25, joined: '2024-06-01', role: 'editor' },
|
|
50
|
-
{ id: '3', name: 'Carol', age: 40, joined: '2025-02-10', role: 'viewer' },
|
|
51
|
-
{ id: '4', name: 'Dave', age: 35, joined: '2025-08-22', role: 'editor' },
|
|
52
|
-
]);
|
|
53
|
-
protected readonly getId = (row: Row) => row.id;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async function getDir() {
|
|
57
|
-
const r = await render(Host);
|
|
58
|
-
return r.fixture.debugElement.children[0].injector.get(KjTable<Row>);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
describe('text filter model', () => {
|
|
62
|
-
it('contains', async () => {
|
|
63
|
-
const { gridApi } = await getDir();
|
|
64
|
-
gridApi.filter.set('name', {
|
|
65
|
-
filterType: 'text',
|
|
66
|
-
type: 'contains',
|
|
67
|
-
filter: 'al',
|
|
68
|
-
} as KjTextFilterModel);
|
|
69
|
-
expect(gridApi.rows.filteredCount()).toBe(1); // Alice
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('startsWith / endsWith', async () => {
|
|
73
|
-
const { gridApi } = await getDir();
|
|
74
|
-
gridApi.filter.set('name', { filterType: 'text', type: 'startsWith', filter: 'B' });
|
|
75
|
-
expect(gridApi.rows.filteredCount()).toBe(1);
|
|
76
|
-
gridApi.filter.set('name', { filterType: 'text', type: 'endsWith', filter: 'l' });
|
|
77
|
-
expect(gridApi.rows.filteredCount()).toBe(1); // Carol
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('blank / notBlank', async () => {
|
|
81
|
-
const { gridApi } = await getDir();
|
|
82
|
-
gridApi.filter.set('name', { filterType: 'text', type: 'notBlank' });
|
|
83
|
-
expect(gridApi.rows.filteredCount()).toBe(4);
|
|
84
|
-
gridApi.filter.set('name', { filterType: 'text', type: 'blank' });
|
|
85
|
-
expect(gridApi.rows.filteredCount()).toBe(0);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('number filter model', () => {
|
|
90
|
-
it('equals / notEquals', async () => {
|
|
91
|
-
const { gridApi } = await getDir();
|
|
92
|
-
gridApi.filter.set('age', { filterType: 'number', type: 'equals', filter: 30 });
|
|
93
|
-
expect(gridApi.rows.filteredCount()).toBe(1);
|
|
94
|
-
gridApi.filter.set('age', { filterType: 'number', type: 'notEquals', filter: 30 });
|
|
95
|
-
expect(gridApi.rows.filteredCount()).toBe(3);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('inRange', async () => {
|
|
99
|
-
const { gridApi } = await getDir();
|
|
100
|
-
const model: KjNumberFilterModel = {
|
|
101
|
-
filterType: 'number',
|
|
102
|
-
type: 'inRange',
|
|
103
|
-
filter: 28,
|
|
104
|
-
filterTo: 36,
|
|
105
|
-
};
|
|
106
|
-
gridApi.filter.set('age', model);
|
|
107
|
-
expect(gridApi.rows.filteredCount()).toBe(2); // 30, 35
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('greaterThan / lessThanOrEqual', async () => {
|
|
111
|
-
const { gridApi } = await getDir();
|
|
112
|
-
gridApi.filter.set('age', { filterType: 'number', type: 'greaterThan', filter: 30 });
|
|
113
|
-
expect(gridApi.rows.filteredCount()).toBe(2);
|
|
114
|
-
gridApi.filter.set('age', { filterType: 'number', type: 'lessThanOrEqual', filter: 30 });
|
|
115
|
-
expect(gridApi.rows.filteredCount()).toBe(2);
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
describe('date filter model', () => {
|
|
120
|
-
it('inRange', async () => {
|
|
121
|
-
const { gridApi } = await getDir();
|
|
122
|
-
const model: KjDateFilterModel = {
|
|
123
|
-
filterType: 'date',
|
|
124
|
-
type: 'inRange',
|
|
125
|
-
dateFrom: '2024-01-01',
|
|
126
|
-
dateTo: '2024-12-31',
|
|
127
|
-
};
|
|
128
|
-
gridApi.filter.set('joined', model);
|
|
129
|
-
expect(gridApi.rows.filteredCount()).toBe(2);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('greaterThan / lessThan', async () => {
|
|
133
|
-
const { gridApi } = await getDir();
|
|
134
|
-
gridApi.filter.set('joined', {
|
|
135
|
-
filterType: 'date',
|
|
136
|
-
type: 'greaterThan',
|
|
137
|
-
dateFrom: '2025-01-01',
|
|
138
|
-
});
|
|
139
|
-
expect(gridApi.rows.filteredCount()).toBe(2);
|
|
140
|
-
gridApi.filter.set('joined', { filterType: 'date', type: 'lessThan', dateFrom: '2024-06-01' });
|
|
141
|
-
expect(gridApi.rows.filteredCount()).toBe(1);
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
describe('set filter model', () => {
|
|
146
|
-
it('matches any of the listed values', async () => {
|
|
147
|
-
const { gridApi } = await getDir();
|
|
148
|
-
const model: KjSetFilterModel = { filterType: 'set', values: ['admin', 'editor'] };
|
|
149
|
-
gridApi.filter.set('role', model);
|
|
150
|
-
expect(gridApi.rows.filteredCount()).toBe(3);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('empty values = no filter', async () => {
|
|
154
|
-
const { gridApi } = await getDir();
|
|
155
|
-
gridApi.filter.set('role', { filterType: 'set', values: [] });
|
|
156
|
-
expect(gridApi.rows.filteredCount()).toBe(4);
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe('multi-condition filter (AND/OR)', () => {
|
|
161
|
-
it('AND', async () => {
|
|
162
|
-
const { gridApi } = await getDir();
|
|
163
|
-
const model: KjMultiConditionFilterModel = {
|
|
164
|
-
filterType: 'multi',
|
|
165
|
-
operator: 'AND',
|
|
166
|
-
conditions: [
|
|
167
|
-
{ filterType: 'number', type: 'greaterThan', filter: 28 },
|
|
168
|
-
{ filterType: 'number', type: 'lessThan', filter: 36 },
|
|
169
|
-
],
|
|
170
|
-
};
|
|
171
|
-
// Apply against age column — kjMultiFilterFn dispatches by inner filterType.
|
|
172
|
-
// Use direct fn invocation here because TanStack columns only have one filterFn at a time.
|
|
173
|
-
const passed = gridApi.rows
|
|
174
|
-
.all()
|
|
175
|
-
.filter((r) =>
|
|
176
|
-
kjMultiFilterFn(
|
|
177
|
-
{ getValue: () => r.age } as unknown as Parameters<typeof kjMultiFilterFn>[0],
|
|
178
|
-
'age',
|
|
179
|
-
model,
|
|
180
|
-
),
|
|
181
|
-
);
|
|
182
|
-
expect(passed.length).toBe(2);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('OR', async () => {
|
|
186
|
-
const { gridApi } = await getDir();
|
|
187
|
-
const model: KjMultiConditionFilterModel = {
|
|
188
|
-
filterType: 'multi',
|
|
189
|
-
operator: 'OR',
|
|
190
|
-
conditions: [
|
|
191
|
-
{ filterType: 'number', type: 'lessThan', filter: 26 },
|
|
192
|
-
{ filterType: 'number', type: 'greaterThan', filter: 38 },
|
|
193
|
-
],
|
|
194
|
-
};
|
|
195
|
-
const passed = gridApi.rows
|
|
196
|
-
.all()
|
|
197
|
-
.filter((r) =>
|
|
198
|
-
kjMultiFilterFn(
|
|
199
|
-
{ getValue: () => r.age } as unknown as Parameters<typeof kjMultiFilterFn>[0],
|
|
200
|
-
'age',
|
|
201
|
-
model,
|
|
202
|
-
),
|
|
203
|
-
);
|
|
204
|
-
expect(passed.length).toBe(2);
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
describe('gridApi.filter.getModel / setModel', () => {
|
|
209
|
-
it('getModel returns structured models keyed by column id', async () => {
|
|
210
|
-
const { gridApi } = await getDir();
|
|
211
|
-
gridApi.filter.set('name', { filterType: 'text', type: 'contains', filter: 'al' });
|
|
212
|
-
gridApi.filter.set('age', { filterType: 'number', type: 'equals', filter: 30 });
|
|
213
|
-
const model = gridApi.filter.getModel();
|
|
214
|
-
expect(model['name']).toEqual({ filterType: 'text', type: 'contains', filter: 'al' });
|
|
215
|
-
expect(model['age']).toEqual({ filterType: 'number', type: 'equals', filter: 30 });
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it('getModel omits raw (non-model) entries', async () => {
|
|
219
|
-
const { gridApi } = await getDir();
|
|
220
|
-
gridApi.filter.set('name', 'alice'); // legacy raw value
|
|
221
|
-
expect(gridApi.filter.getModel()).toEqual({});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('setModel replaces every column filter at once', async () => {
|
|
225
|
-
const { gridApi } = await getDir();
|
|
226
|
-
gridApi.filter.set('age', { filterType: 'number', type: 'equals', filter: 30 });
|
|
227
|
-
gridApi.filter.setModel({
|
|
228
|
-
role: { filterType: 'set', values: ['editor'] },
|
|
229
|
-
});
|
|
230
|
-
expect(gridApi.filter.getModelFor('age')).toBeUndefined();
|
|
231
|
-
expect(gridApi.filter.getModelFor('role')).toEqual({ filterType: 'set', values: ['editor'] });
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it('setModel(null) clears everything', async () => {
|
|
235
|
-
const { gridApi } = await getDir();
|
|
236
|
-
gridApi.filter.set('age', { filterType: 'number', type: 'equals', filter: 30 });
|
|
237
|
-
gridApi.filter.setModel(null);
|
|
238
|
-
expect(gridApi.filter.all()).toEqual([]);
|
|
239
|
-
});
|
|
240
|
-
});
|