@nadicodeai/ui 12.1.101 → 12.1.103
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/dist/components/accordion.d.ts +38 -12
- package/dist/components/accordion.d.ts.map +1 -1
- package/dist/components/accordion.js +36 -15
- package/dist/components/account-menu.d.ts +18 -18
- package/dist/components/account-menu.d.ts.map +1 -1
- package/dist/components/account-menu.js +17 -13
- package/dist/components/action-menu.d.ts +20 -19
- package/dist/components/action-menu.d.ts.map +1 -1
- package/dist/components/action-menu.js +22 -15
- package/dist/components/action-status.d.ts +14 -10
- package/dist/components/action-status.d.ts.map +1 -1
- package/dist/components/action-status.js +14 -10
- package/dist/components/activity-calendar.d.ts +3 -1
- package/dist/components/activity-calendar.d.ts.map +1 -1
- package/dist/components/activity-calendar.js +16 -2
- package/dist/components/activity-feed.d.ts +2 -2
- package/dist/components/activity-feed.d.ts.map +1 -1
- package/dist/components/activity-feed.js +14 -5
- package/dist/components/agent-card.d.ts +11 -5
- package/dist/components/agent-card.d.ts.map +1 -1
- package/dist/components/agent-card.js +13 -7
- package/dist/components/agent-list-row.js +1 -1
- package/dist/components/agent-orb-appearance.d.ts +7 -1
- package/dist/components/agent-orb-appearance.d.ts.map +1 -1
- package/dist/components/agent-orb-appearance.js +26 -0
- package/dist/components/agent-profile.d.ts +8 -7
- package/dist/components/agent-profile.d.ts.map +1 -1
- package/dist/components/agent-profile.js +6 -6
- package/dist/components/alert-dialog.d.ts +25 -16
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +30 -18
- package/dist/components/alert.d.ts +1 -1
- package/dist/components/avatar.d.ts +83 -17
- package/dist/components/avatar.d.ts.map +1 -1
- package/dist/components/avatar.js +89 -23
- package/dist/components/badge.d.ts +59 -8
- package/dist/components/badge.d.ts.map +1 -1
- package/dist/components/badge.js +57 -14
- package/dist/components/breadcrumb.d.ts +18 -7
- package/dist/components/breadcrumb.d.ts.map +1 -1
- package/dist/components/breadcrumb.js +37 -13
- package/dist/components/button-group.d.ts +12 -15
- package/dist/components/button-group.d.ts.map +1 -1
- package/dist/components/button-group.js +13 -17
- package/dist/components/button.d.ts +126 -23
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +164 -39
- package/dist/components/calendar.d.ts +26 -15
- package/dist/components/calendar.d.ts.map +1 -1
- package/dist/components/calendar.js +60 -46
- package/dist/components/card-row.d.ts +13 -5
- package/dist/components/card-row.d.ts.map +1 -1
- package/dist/components/card-row.js +24 -10
- package/dist/components/card.d.ts +6 -12
- package/dist/components/card.d.ts.map +1 -1
- package/dist/components/card.js +11 -16
- package/dist/components/carousel.d.ts +3 -3
- package/dist/components/carousel.d.ts.map +1 -1
- package/dist/components/carousel.js +7 -7
- package/dist/components/catalog-drawer.d.ts +7 -7
- package/dist/components/catalog-drawer.d.ts.map +1 -1
- package/dist/components/catalog-drawer.js +6 -6
- package/dist/components/chart-area-stacked.d.ts +1 -1
- package/dist/components/chart-area-stacked.d.ts.map +1 -1
- package/dist/components/chart-area-stacked.js +4 -4
- package/dist/components/chart-axis.d.ts +14 -1
- package/dist/components/chart-axis.d.ts.map +1 -1
- package/dist/components/chart-axis.js +11 -1
- package/dist/components/chart-bar-horizontal.d.ts +2 -2
- package/dist/components/chart-bar-horizontal.d.ts.map +1 -1
- package/dist/components/chart-bar-horizontal.js +14 -5
- package/dist/components/chart-bar-multiple.d.ts +1 -1
- package/dist/components/chart-bar-multiple.d.ts.map +1 -1
- package/dist/components/chart-bar-multiple.js +3 -3
- package/dist/components/chart-bar-stacked.d.ts +1 -1
- package/dist/components/chart-bar-stacked.d.ts.map +1 -1
- package/dist/components/chart-bar-stacked.js +3 -3
- package/dist/components/chart-card.d.ts +17 -6
- package/dist/components/chart-card.d.ts.map +1 -1
- package/dist/components/chart-card.js +11 -4
- package/dist/components/chart-date-range-control.d.ts +18 -9
- package/dist/components/chart-date-range-control.d.ts.map +1 -1
- package/dist/components/chart-date-range-control.js +43 -47
- package/dist/components/chart-sparkline.d.ts +4 -3
- package/dist/components/chart-sparkline.d.ts.map +1 -1
- package/dist/components/chart-sparkline.js +6 -5
- package/dist/components/check-counts.d.ts +44 -0
- package/dist/components/check-counts.d.ts.map +1 -0
- package/dist/components/check-counts.js +51 -0
- package/dist/components/checkbox.d.ts +39 -11
- package/dist/components/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox.js +38 -11
- package/dist/components/choicebox.d.ts +96 -0
- package/dist/components/choicebox.d.ts.map +1 -0
- package/dist/components/choicebox.js +113 -0
- package/dist/components/clearable-input.d.ts +57 -0
- package/dist/components/clearable-input.d.ts.map +1 -0
- package/dist/components/clearable-input.js +58 -0
- package/dist/components/code-block.d.ts +77 -17
- package/dist/components/code-block.d.ts.map +1 -1
- package/dist/components/code-block.js +85 -15
- package/dist/components/collapsible.d.ts +27 -10
- package/dist/components/collapsible.d.ts.map +1 -1
- package/dist/components/collapsible.js +24 -9
- package/dist/components/collection-filters.d.ts +3 -1
- package/dist/components/collection-filters.d.ts.map +1 -1
- package/dist/components/collection-filters.js +7 -9
- package/dist/components/collection-page.d.ts +31 -10
- package/dist/components/collection-page.d.ts.map +1 -1
- package/dist/components/collection-page.js +14 -13
- package/dist/components/collection-search.d.ts +32 -10
- package/dist/components/collection-search.d.ts.map +1 -1
- package/dist/components/collection-search.js +24 -13
- package/dist/components/collection-sort.d.ts.map +1 -1
- package/dist/components/collection-sort.js +2 -2
- package/dist/components/collection-toolbar.d.ts +5 -2
- package/dist/components/collection-toolbar.d.ts.map +1 -1
- package/dist/components/collection-toolbar.js +7 -4
- package/dist/components/combobox.d.ts +97 -22
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +80 -28
- package/dist/components/command.d.ts +34 -21
- package/dist/components/command.d.ts.map +1 -1
- package/dist/components/command.js +33 -25
- package/dist/components/confirm-dialog.d.ts +23 -6
- package/dist/components/confirm-dialog.d.ts.map +1 -1
- package/dist/components/confirm-dialog.js +32 -13
- package/dist/components/context-menu.d.ts +14 -10
- package/dist/components/context-menu.d.ts.map +1 -1
- package/dist/components/context-menu.js +17 -12
- package/dist/components/copy-button.d.ts +5 -2
- package/dist/components/copy-button.d.ts.map +1 -1
- package/dist/components/copy-button.js +16 -8
- package/dist/components/data-table.d.ts +120 -54
- package/dist/components/data-table.d.ts.map +1 -1
- package/dist/components/data-table.js +163 -92
- package/dist/components/desktop-shell.d.ts +4 -2
- package/dist/components/desktop-shell.d.ts.map +1 -1
- package/dist/components/desktop-shell.js +3 -3
- package/dist/components/dialog.d.ts +63 -24
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js +52 -31
- package/dist/components/disclosure-row.d.ts +1 -2
- package/dist/components/disclosure-row.d.ts.map +1 -1
- package/dist/components/disclosure-row.js +1 -2
- package/dist/components/disclosure.d.ts +1 -1
- package/dist/components/disclosure.js +1 -1
- package/dist/components/drawer.d.ts +33 -12
- package/dist/components/drawer.d.ts.map +1 -1
- package/dist/components/drawer.js +47 -35
- package/dist/components/dropdown-menu.d.ts +59 -14
- package/dist/components/dropdown-menu.d.ts.map +1 -1
- package/dist/components/dropdown-menu.js +58 -26
- package/dist/components/empty-state.d.ts +35 -12
- package/dist/components/empty-state.d.ts.map +1 -1
- package/dist/components/empty-state.js +35 -17
- package/dist/components/entry-scene.d.ts +4 -4
- package/dist/components/entry-scene.d.ts.map +1 -1
- package/dist/components/entry-scene.js +2 -2
- package/dist/components/field.d.ts +44 -14
- package/dist/components/field.d.ts.map +1 -1
- package/dist/components/field.js +49 -20
- package/dist/components/file-diff.d.ts.map +1 -1
- package/dist/components/file-diff.js +3 -4
- package/dist/components/form-dialog.d.ts +7 -7
- package/dist/components/form-dialog.d.ts.map +1 -1
- package/dist/components/form-dialog.js +13 -11
- package/dist/components/form-drawer.d.ts +10 -7
- package/dist/components/form-drawer.d.ts.map +1 -1
- package/dist/components/form-drawer.js +11 -10
- package/dist/components/gauge.d.ts +64 -0
- package/dist/components/gauge.d.ts.map +1 -0
- package/dist/components/gauge.js +73 -0
- package/dist/components/hover-card.d.ts +72 -14
- package/dist/components/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card.js +51 -17
- package/dist/components/identity-mark.d.ts +8 -1
- package/dist/components/identity-mark.d.ts.map +1 -1
- package/dist/components/identity-mark.js +31 -5
- package/dist/components/input-group.d.ts +44 -21
- package/dist/components/input-group.d.ts.map +1 -1
- package/dist/components/input-group.js +74 -27
- package/dist/components/input.d.ts +64 -12
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +51 -15
- package/dist/components/item.d.ts +37 -15
- package/dist/components/item.d.ts.map +1 -1
- package/dist/components/item.js +41 -22
- package/dist/components/kbd.d.ts +49 -13
- package/dist/components/kbd.d.ts.map +1 -1
- package/dist/components/kbd.js +115 -16
- package/dist/components/kpi-card.d.ts +12 -4
- package/dist/components/kpi-card.d.ts.map +1 -1
- package/dist/components/kpi-card.js +13 -4
- package/dist/components/label.d.ts +17 -10
- package/dist/components/label.d.ts.map +1 -1
- package/dist/components/label.js +18 -11
- package/dist/components/library-shelf.d.ts +6 -6
- package/dist/components/library-shelf.d.ts.map +1 -1
- package/dist/components/library-shelf.js +5 -5
- package/dist/components/load-more-button.d.ts +35 -0
- package/dist/components/load-more-button.d.ts.map +1 -0
- package/dist/components/load-more-button.js +26 -0
- package/dist/components/menu-choice-row.d.ts +6 -8
- package/dist/components/menu-choice-row.d.ts.map +1 -1
- package/dist/components/menu-choice-row.js +8 -8
- package/dist/components/message-notice.d.ts +8 -13
- package/dist/components/message-notice.d.ts.map +1 -1
- package/dist/components/message-notice.js +25 -22
- package/dist/components/middle-truncate.d.ts +33 -0
- package/dist/components/middle-truncate.d.ts.map +1 -0
- package/dist/components/middle-truncate.js +72 -0
- package/dist/components/multi-select.d.ts +94 -0
- package/dist/components/multi-select.d.ts.map +1 -0
- package/dist/components/multi-select.js +132 -0
- package/dist/components/native-select.d.ts +37 -13
- package/dist/components/native-select.d.ts.map +1 -1
- package/dist/components/native-select.js +27 -11
- package/dist/components/notice-banner.d.ts +17 -10
- package/dist/components/notice-banner.d.ts.map +1 -1
- package/dist/components/notice-banner.js +12 -11
- package/dist/components/numbered-steps.d.ts +10 -4
- package/dist/components/numbered-steps.d.ts.map +1 -1
- package/dist/components/numbered-steps.js +9 -7
- package/dist/components/object-page.d.ts +40 -14
- package/dist/components/object-page.d.ts.map +1 -1
- package/dist/components/object-page.js +12 -10
- package/dist/components/object-workspace.d.ts +29 -10
- package/dist/components/object-workspace.d.ts.map +1 -1
- package/dist/components/object-workspace.js +18 -8
- package/dist/components/overview-page.d.ts +2 -2
- package/dist/components/overview-page.d.ts.map +1 -1
- package/dist/components/overview-page.js +8 -7
- package/dist/components/page-actions.d.ts +28 -8
- package/dist/components/page-actions.d.ts.map +1 -1
- package/dist/components/page-actions.js +22 -25
- package/dist/components/page-header.d.ts +11 -4
- package/dist/components/page-header.d.ts.map +1 -1
- package/dist/components/page-header.js +10 -5
- package/dist/components/pending-label.d.ts +6 -5
- package/dist/components/pending-label.d.ts.map +1 -1
- package/dist/components/pending-label.js +14 -6
- package/dist/components/picture-label.d.ts +2 -2
- package/dist/components/picture-label.d.ts.map +1 -1
- package/dist/components/picture-label.js +3 -3
- package/dist/components/portal-sidebar-frame.d.ts +9 -21
- package/dist/components/portal-sidebar-frame.d.ts.map +1 -1
- package/dist/components/portal-sidebar-frame.js +13 -27
- package/dist/components/progress-checklist.d.ts +46 -0
- package/dist/components/progress-checklist.d.ts.map +1 -0
- package/dist/components/progress-checklist.js +46 -0
- package/dist/components/progress.d.ts +48 -8
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/progress.js +92 -16
- package/dist/components/prose.d.ts +19 -0
- package/dist/components/prose.d.ts.map +1 -0
- package/dist/components/prose.js +29 -0
- package/dist/components/radio-group.d.ts +51 -12
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +42 -12
- package/dist/components/reading-column.js +1 -1
- package/dist/components/record-identity.d.ts +6 -5
- package/dist/components/record-identity.d.ts.map +1 -1
- package/dist/components/record-identity.js +12 -3
- package/dist/components/record-list.d.ts +117 -27
- package/dist/components/record-list.d.ts.map +1 -1
- package/dist/components/record-list.js +185 -55
- package/dist/components/record-time.d.ts +20 -7
- package/dist/components/record-time.d.ts.map +1 -1
- package/dist/components/record-time.js +38 -19
- package/dist/components/resizable.d.ts +7 -5
- package/dist/components/resizable.d.ts.map +1 -1
- package/dist/components/resizable.js +6 -6
- package/dist/components/scope-switcher.d.ts +2 -0
- package/dist/components/scope-switcher.d.ts.map +1 -1
- package/dist/components/scope-switcher.js +2 -2
- package/dist/components/scroll-area.d.ts +47 -11
- package/dist/components/scroll-area.d.ts.map +1 -1
- package/dist/components/scroll-area.js +72 -14
- package/dist/components/segmented-control.d.ts +82 -0
- package/dist/components/segmented-control.d.ts.map +1 -0
- package/dist/components/segmented-control.js +90 -0
- package/dist/components/select.d.ts +55 -15
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +62 -19
- package/dist/components/separator.d.ts +12 -5
- package/dist/components/separator.d.ts.map +1 -1
- package/dist/components/separator.js +11 -6
- package/dist/components/settings-facts.d.ts +34 -14
- package/dist/components/settings-facts.d.ts.map +1 -1
- package/dist/components/settings-facts.js +21 -12
- package/dist/components/settings-page.d.ts +4 -4
- package/dist/components/settings-page.js +5 -5
- package/dist/components/settings-section.d.ts +160 -34
- package/dist/components/settings-section.d.ts.map +1 -1
- package/dist/components/settings-section.js +92 -39
- package/dist/components/sheet.d.ts +47 -16
- package/dist/components/sheet.d.ts.map +1 -1
- package/dist/components/sheet.js +40 -19
- package/dist/components/sidebar-sections.d.ts +16 -12
- package/dist/components/sidebar-sections.d.ts.map +1 -1
- package/dist/components/sidebar-sections.js +30 -15
- package/dist/components/sidebar.d.ts +117 -21
- package/dist/components/sidebar.d.ts.map +1 -1
- package/dist/components/sidebar.js +180 -55
- package/dist/components/skeleton.d.ts +54 -8
- package/dist/components/skeleton.d.ts.map +1 -1
- package/dist/components/skeleton.js +44 -9
- package/dist/components/slider.d.ts +53 -11
- package/dist/components/slider.d.ts.map +1 -1
- package/dist/components/slider.js +71 -17
- package/dist/components/snippet.d.ts +57 -0
- package/dist/components/snippet.d.ts.map +1 -0
- package/dist/components/snippet.js +60 -0
- package/dist/components/sonner.d.ts +13 -14
- package/dist/components/sonner.d.ts.map +1 -1
- package/dist/components/sonner.js +25 -22
- package/dist/components/status-badge.d.ts +37 -11
- package/dist/components/status-badge.d.ts.map +1 -1
- package/dist/components/status-badge.js +63 -15
- package/dist/components/status-dot.d.ts +42 -11
- package/dist/components/status-dot.d.ts.map +1 -1
- package/dist/components/status-dot.js +40 -11
- package/dist/components/switch.d.ts +43 -12
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/switch.js +42 -12
- package/dist/components/table-card.d.ts +21 -12
- package/dist/components/table-card.d.ts.map +1 -1
- package/dist/components/table-card.js +17 -9
- package/dist/components/table-layouts.d.ts +40 -8
- package/dist/components/table-layouts.d.ts.map +1 -1
- package/dist/components/table-layouts.js +52 -8
- package/dist/components/table-value.d.ts +4 -3
- package/dist/components/table-value.d.ts.map +1 -1
- package/dist/components/table-value.js +6 -5
- package/dist/components/table.d.ts +62 -25
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/table.js +62 -26
- package/dist/components/tabs.d.ts +86 -17
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +93 -22
- package/dist/components/text-link.d.ts +4 -1
- package/dist/components/text-link.d.ts.map +1 -1
- package/dist/components/text-link.js +4 -1
- package/dist/components/text-with-copy-button.d.ts +30 -0
- package/dist/components/text-with-copy-button.d.ts.map +1 -0
- package/dist/components/text-with-copy-button.js +32 -0
- package/dist/components/textarea.d.ts +40 -10
- package/dist/components/textarea.d.ts.map +1 -1
- package/dist/components/textarea.js +50 -11
- package/dist/components/theme-mode-switcher.d.ts +20 -3
- package/dist/components/theme-mode-switcher.d.ts.map +1 -1
- package/dist/components/theme-mode-switcher.js +23 -6
- package/dist/components/toggle-group.d.ts +28 -8
- package/dist/components/toggle-group.d.ts.map +1 -1
- package/dist/components/toggle-group.js +12 -6
- package/dist/components/toggle.d.ts +6 -3
- package/dist/components/toggle.d.ts.map +1 -1
- package/dist/components/toggle.js +10 -7
- package/dist/components/tooltip.d.ts +43 -12
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +45 -16
- package/dist/components/trend-badge.js +1 -1
- package/dist/components/update-card.js +1 -1
- package/dist/eslint/index.js +82 -0
- package/dist/eslint/rules/badge-is-static-label.js +93 -0
- package/dist/eslint/rules/button-icon-slot.js +102 -0
- package/dist/eslint/rules/button-link-for-navigation.js +146 -0
- package/dist/eslint/rules/button-no-aria-label-with-text.js +75 -0
- package/dist/eslint/rules/button-type-roles-only-in-buttons.js +83 -0
- package/dist/eslint/rules/choice-control-has-a-name.js +98 -0
- package/dist/eslint/rules/choice-group-in-fieldset.js +86 -0
- package/dist/eslint/rules/command-shortcut-single-owner.js +118 -0
- package/dist/eslint/rules/confirm-dialog-words.js +63 -0
- package/dist/eslint/rules/data-table-one-unsized-column.js +96 -0
- package/dist/eslint/rules/destructive-action-placement.js +69 -0
- package/dist/eslint/rules/disabled-choice-says-why.js +71 -0
- package/dist/eslint/rules/ellipsis-opens-a-dialog.js +110 -0
- package/dist/eslint/rules/input-group-owners.js +155 -0
- package/dist/eslint/rules/kbd-children-no-modifier-text.js +128 -0
- package/dist/eslint/rules/literal-text.js +41 -0
- package/dist/eslint/rules/middle-truncate-placement.js +69 -0
- package/dist/eslint/rules/no-bare-button-label.js +55 -0
- package/dist/eslint/rules/no-control-in-read-only-surface.js +106 -0
- package/dist/eslint/rules/no-hand-built-busy.js +104 -0
- package/dist/eslint/rules/no-hand-built-theme-picker.js +144 -0
- package/dist/eslint/rules/no-hand-built-tile.js +41 -0
- package/dist/eslint/rules/no-hand-formatted-date.js +87 -0
- package/dist/eslint/rules/no-hand-stacked-avatars.js +67 -0
- package/dist/eslint/rules/no-nested-collapse.js +60 -0
- package/dist/eslint/rules/no-search-in-form.js +47 -0
- package/dist/eslint/rules/no-shadcn-appearance-override.js +2 -16
- package/dist/eslint/rules/no-shell-prompt-in-snippet.js +74 -0
- package/dist/eslint/rules/no-stock-error-words.js +56 -0
- package/dist/eslint/rules/no-tooltip-around-labelled-field.js +72 -0
- package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +57 -0
- package/dist/eslint/rules/one-submenu-level.js +43 -0
- package/dist/eslint/rules/one-toast-per-flow.js +91 -0
- package/dist/eslint/rules/option-count.js +167 -0
- package/dist/eslint/rules/page-command-link-not-render.js +43 -0
- package/dist/eslint/rules/progress-needs-name.js +57 -0
- package/dist/eslint/rules/settings-limit-in-footer.js +94 -0
- package/dist/eslint/rules/skeleton-in-region.js +80 -0
- package/dist/eslint/rules/sortable-heading-uses-sort.js +79 -0
- package/dist/eslint/rules/table-cell-inset-owner.js +107 -0
- package/dist/eslint/rules/tabs-selection-is-controlled.js +47 -0
- package/dist/eslint/rules/tooltip-only-arrow.js +38 -0
- package/dist/eslint/rules/tooltip-trigger-accessible-name.js +114 -0
- package/dist/eslint/strict-design-system.js +21 -7
- package/dist/index.d.ts +13 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -13
- package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
- package/dist/internal/assistant-ui/attachment.js +2 -2
- package/dist/internal/assistant-ui/reasoning.d.ts +1 -1
- package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tool-fallback.js +1 -1
- package/dist/internal/assistant-ui/tool-group.d.ts +1 -1
- package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +2 -3
- package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
- package/dist/internal/catalog-list.js +2 -2
- package/dist/internal/collection-note.d.ts +23 -0
- package/dist/internal/collection-note.d.ts.map +1 -0
- package/dist/internal/collection-note.js +17 -0
- package/dist/internal/collection-rail.d.ts +57 -0
- package/dist/internal/collection-rail.d.ts.map +1 -0
- package/dist/internal/collection-rail.js +33 -0
- package/dist/internal/company-logo.d.ts +18 -0
- package/dist/internal/company-logo.d.ts.map +1 -0
- package/dist/internal/company-logo.js +14 -0
- package/dist/internal/control-name.d.ts +12 -0
- package/dist/internal/control-name.d.ts.map +1 -0
- package/dist/internal/control-name.js +1 -0
- package/dist/internal/diff-line.d.ts +9 -0
- package/dist/internal/diff-line.d.ts.map +1 -0
- package/dist/internal/diff-line.js +8 -0
- package/dist/internal/empty.d.ts +8 -4
- package/dist/internal/empty.d.ts.map +1 -1
- package/dist/internal/empty.js +14 -8
- package/dist/internal/field-frame.d.ts +33 -0
- package/dist/internal/field-frame.d.ts.map +1 -0
- package/dist/internal/field-frame.js +20 -0
- package/dist/internal/final-focus.d.ts +8 -0
- package/dist/internal/final-focus.d.ts.map +1 -0
- package/dist/internal/final-focus.js +10 -0
- package/dist/internal/footer-strip.d.ts.map +1 -1
- package/dist/internal/footer-strip.js +3 -1
- package/dist/internal/form-submit.d.ts +9 -5
- package/dist/internal/form-submit.d.ts.map +1 -1
- package/dist/internal/form-submit.js +31 -2
- package/dist/internal/input-box.d.ts +26 -0
- package/dist/internal/input-box.d.ts.map +1 -0
- package/dist/internal/input-box.js +59 -0
- package/dist/internal/menu-surface.d.ts +10 -3
- package/dist/internal/menu-surface.d.ts.map +1 -1
- package/dist/internal/menu-surface.js +10 -3
- package/dist/internal/notice.d.ts +25 -0
- package/dist/internal/notice.d.ts.map +1 -0
- package/dist/internal/notice.js +33 -0
- package/dist/internal/overlay-stem.d.ts +5 -0
- package/dist/internal/overlay-stem.d.ts.map +1 -0
- package/dist/internal/overlay-stem.js +7 -0
- package/dist/internal/phone-sheet.d.ts +4 -0
- package/dist/internal/phone-sheet.d.ts.map +1 -0
- package/dist/internal/phone-sheet.js +2 -0
- package/dist/internal/present-content.d.ts +3 -0
- package/dist/internal/present-content.d.ts.map +1 -0
- package/dist/internal/present-content.js +1 -0
- package/dist/internal/record-menu-items.d.ts +4 -3
- package/dist/internal/record-menu-items.d.ts.map +1 -1
- package/dist/internal/record-menu-items.js +21 -6
- package/dist/internal/settings-save.d.ts +9 -2
- package/dist/internal/settings-save.d.ts.map +1 -1
- package/dist/internal/settings-save.js +9 -6
- package/dist/internal/table-compact-line.d.ts +38 -0
- package/dist/internal/table-compact-line.d.ts.map +1 -0
- package/dist/internal/table-compact-line.js +35 -0
- package/dist/internal/title-when-cut.d.ts +8 -0
- package/dist/internal/title-when-cut.d.ts.map +1 -0
- package/dist/internal/title-when-cut.js +22 -0
- package/dist/internal/unsaved-guard.d.ts +18 -0
- package/dist/internal/unsaved-guard.d.ts.map +1 -0
- package/dist/internal/unsaved-guard.js +31 -0
- package/dist/lib/merge-tokens.generated.js +2 -2
- package/dist/showcase/foundations.d.ts.map +1 -1
- package/dist/showcase/foundations.js +10 -2
- package/dist/showcase/specimens/actions.d.ts +2 -0
- package/dist/showcase/specimens/actions.d.ts.map +1 -1
- package/dist/showcase/specimens/actions.js +30 -5
- package/dist/showcase/specimens/charts.d.ts.map +1 -1
- package/dist/showcase/specimens/charts.js +22 -13
- package/dist/showcase/specimens/choices.d.ts +14 -3
- package/dist/showcase/specimens/choices.d.ts.map +1 -1
- package/dist/showcase/specimens/choices.js +93 -13
- package/dist/showcase/specimens/compositions.d.ts.map +1 -1
- package/dist/showcase/specimens/compositions.js +136 -23
- package/dist/showcase/specimens/data.d.ts +12 -7
- package/dist/showcase/specimens/data.d.ts.map +1 -1
- package/dist/showcase/specimens/data.js +139 -35
- package/dist/showcase/specimens/feedback.d.ts +2 -0
- package/dist/showcase/specimens/feedback.d.ts.map +1 -1
- package/dist/showcase/specimens/feedback.js +39 -15
- package/dist/showcase/specimens/index.d.ts +20 -12
- package/dist/showcase/specimens/index.d.ts.map +1 -1
- package/dist/showcase/specimens/inputs.d.ts +4 -2
- package/dist/showcase/specimens/inputs.d.ts.map +1 -1
- package/dist/showcase/specimens/inputs.js +62 -19
- package/dist/showcase/specimens/menus.d.ts +0 -1
- package/dist/showcase/specimens/menus.d.ts.map +1 -1
- package/dist/showcase/specimens/menus.js +47 -18
- package/dist/showcase/specimens/navigation.d.ts +6 -4
- package/dist/showcase/specimens/navigation.d.ts.map +1 -1
- package/dist/showcase/specimens/navigation.js +61 -32
- package/dist/showcase/specimens/other.d.ts +1 -3
- package/dist/showcase/specimens/other.d.ts.map +1 -1
- package/dist/showcase/specimens/other.js +17 -13
- package/dist/showcase/specimens/status.d.ts +4 -1
- package/dist/showcase/specimens/status.d.ts.map +1 -1
- package/dist/showcase/specimens/status.js +64 -11
- package/dist/showcase/usage.generated.d.ts +1 -1
- package/dist/showcase/usage.generated.d.ts.map +1 -1
- package/dist/showcase/usage.generated.js +637 -549
- package/dist/standalone/index.js +1 -1
- package/dist/styles/components.css +13 -13
- package/dist/styles/globals.css +25 -0
- package/package.json +2 -3
- package/dist/components/approval-row.d.ts +0 -34
- package/dist/components/approval-row.d.ts.map +0 -1
- package/dist/components/approval-row.js +0 -27
- package/dist/components/channel-view.d.ts +0 -112
- package/dist/components/channel-view.d.ts.map +0 -1
- package/dist/components/channel-view.js +0 -84
- package/dist/components/dashboard-shell.d.ts +0 -51
- package/dist/components/dashboard-shell.d.ts.map +0 -1
- package/dist/components/dashboard-shell.js +0 -89
- package/dist/components/direction.d.ts +0 -2
- package/dist/components/direction.d.ts.map +0 -1
- package/dist/components/direction.js +0 -1
- package/dist/components/expandable-block.d.ts +0 -20
- package/dist/components/expandable-block.d.ts.map +0 -1
- package/dist/components/expandable-block.js +0 -32
- package/dist/components/form.d.ts +0 -42
- package/dist/components/form.d.ts.map +0 -1
- package/dist/components/form.js +0 -91
- package/dist/components/label-system.d.ts +0 -17
- package/dist/components/label-system.d.ts.map +0 -1
- package/dist/components/label-system.js +0 -21
- package/dist/components/memory-item.d.ts +0 -21
- package/dist/components/memory-item.d.ts.map +0 -1
- package/dist/components/memory-item.js +0 -18
- package/dist/components/menubar.d.ts +0 -43
- package/dist/components/menubar.d.ts.map +0 -1
- package/dist/components/menubar.js +0 -69
- package/dist/components/navigation-menu.d.ts +0 -26
- package/dist/components/navigation-menu.d.ts.map +0 -1
- package/dist/components/navigation-menu.js +0 -45
- package/dist/components/pagination.d.ts +0 -33
- package/dist/components/pagination.d.ts.map +0 -1
- package/dist/components/pagination.js +0 -41
- package/dist/components/plugin-slot-boundary.d.ts +0 -42
- package/dist/components/plugin-slot-boundary.d.ts.map +0 -1
- package/dist/components/plugin-slot-boundary.js +0 -41
- package/dist/components/status-row.d.ts +0 -32
- package/dist/components/status-row.d.ts.map +0 -1
- package/dist/components/status-row.js +0 -35
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { findBelow, renderedImports, walk } from "./rendered-import.js";
|
|
2
|
+
|
|
3
|
+
const FIELD_LABEL = "FieldLabel";
|
|
4
|
+
const FIELD = "Field";
|
|
5
|
+
const CONTROLS = new Set(["RadioGroupItem", "Checkbox"]);
|
|
6
|
+
|
|
7
|
+
export const noHandBuiltTile = {
|
|
8
|
+
meta: {
|
|
9
|
+
type: "problem",
|
|
10
|
+
docs: {
|
|
11
|
+
description:
|
|
12
|
+
"A bordered selectable tile is a ChoiceboxGroup, never a FieldLabel around a Field with a radio or a checkbox.",
|
|
13
|
+
},
|
|
14
|
+
schema: [],
|
|
15
|
+
messages: {
|
|
16
|
+
"hand-built-tile":
|
|
17
|
+
"A bordered selectable tile is a ChoiceboxGroup with ChoiceboxGroupItem. Options without a description are a plain RadioGroup with a Label for each.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
const importOf = renderedImports(context);
|
|
22
|
+
const { visitorKeys } = context.sourceCode;
|
|
23
|
+
const isRendered = (name) => (node) =>
|
|
24
|
+
node.type === "JSXElement" && name(importOf(node.openingElement.name)?.name);
|
|
25
|
+
const isField = isRendered((name) => name === FIELD);
|
|
26
|
+
const isControl = isRendered((name) => CONTROLS.has(name));
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
JSXElement(node) {
|
|
30
|
+
if (importOf(node.openingElement.name)?.name !== FIELD_LABEL) return;
|
|
31
|
+
let handBuilt = false;
|
|
32
|
+
walk(node, visitorKeys, (child) => {
|
|
33
|
+
if (!isField(child) || !findBelow(child, visitorKeys, isControl)) return true;
|
|
34
|
+
handBuilt = true;
|
|
35
|
+
return "stop";
|
|
36
|
+
});
|
|
37
|
+
if (handBuilt) context.report({ node: node.openingElement, messageId: "hand-built-tile" });
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: `no-restricted-syntax` can match a member named
|
|
3
|
+
* `toLocaleDateString` or `new Intl.DateTimeFormat`, but `toLocaleString` is
|
|
4
|
+
* also how a number is written, so it is a date only when its options object
|
|
5
|
+
* names a date or time part, which a selector cannot read. It reports only a
|
|
6
|
+
* date written into markup (inside a JSX expression of the same function): a
|
|
7
|
+
* helper that returns a chart label, a period name or an email's text has no
|
|
8
|
+
* element to put a RecordTime in.
|
|
9
|
+
*/
|
|
10
|
+
const ALWAYS_DATES = new Set(["toLocaleDateString", "toLocaleTimeString"]);
|
|
11
|
+
const DATE_PARTS = new Set([
|
|
12
|
+
"dateStyle",
|
|
13
|
+
"timeStyle",
|
|
14
|
+
"weekday",
|
|
15
|
+
"era",
|
|
16
|
+
"year",
|
|
17
|
+
"month",
|
|
18
|
+
"day",
|
|
19
|
+
"dayPeriod",
|
|
20
|
+
"hour",
|
|
21
|
+
"minute",
|
|
22
|
+
"second",
|
|
23
|
+
"fractionalSecondDigits",
|
|
24
|
+
"timeZoneName",
|
|
25
|
+
"hour12",
|
|
26
|
+
"hourCycle",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
const isIntlDateTimeFormat = (callee) =>
|
|
30
|
+
callee.type === "MemberExpression" &&
|
|
31
|
+
!callee.computed &&
|
|
32
|
+
callee.object.type === "Identifier" &&
|
|
33
|
+
callee.object.name === "Intl" &&
|
|
34
|
+
callee.property.name === "DateTimeFormat";
|
|
35
|
+
|
|
36
|
+
const namesADatePart = (options) =>
|
|
37
|
+
options?.type === "ObjectExpression" &&
|
|
38
|
+
options.properties.some(
|
|
39
|
+
(property) =>
|
|
40
|
+
property.type === "Property" &&
|
|
41
|
+
!property.computed &&
|
|
42
|
+
property.key.type === "Identifier" &&
|
|
43
|
+
DATE_PARTS.has(property.key.name),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const FUNCTIONS = new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
|
|
47
|
+
|
|
48
|
+
function writtenIntoMarkup(node) {
|
|
49
|
+
for (let current = node.parent; current; current = current.parent) {
|
|
50
|
+
if (current.type === "JSXExpressionContainer") return true;
|
|
51
|
+
if (FUNCTIONS.has(current.type)) return false;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const noHandFormattedDate = {
|
|
57
|
+
meta: {
|
|
58
|
+
type: "problem",
|
|
59
|
+
docs: {
|
|
60
|
+
description: "An app shows a moment through RecordTime, never a hand-formatted date.",
|
|
61
|
+
},
|
|
62
|
+
schema: [],
|
|
63
|
+
messages: {
|
|
64
|
+
"hand-formatted-date":
|
|
65
|
+
"Show a moment with RecordTime from @nadicodeai/ui/components/record-time: it reads relative within a week, then the date, in the viewer's zone and language, with the exact time in a card. A date formatted by hand drifts from the other screens and shows the server's zone.",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
create(context) {
|
|
69
|
+
function check(node) {
|
|
70
|
+
if (!writtenIntoMarkup(node)) return;
|
|
71
|
+
const { callee } = node;
|
|
72
|
+
if (isIntlDateTimeFormat(callee)) {
|
|
73
|
+
context.report({ node, messageId: "hand-formatted-date" });
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (callee.type !== "MemberExpression" || callee.computed) return;
|
|
77
|
+
const name = callee.property.name;
|
|
78
|
+
if (
|
|
79
|
+
ALWAYS_DATES.has(name) ||
|
|
80
|
+
(name === "toLocaleString" && namesADatePart(node.arguments[1]))
|
|
81
|
+
) {
|
|
82
|
+
context.report({ node, messageId: "hand-formatted-date" });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { CallExpression: check, NewExpression: check };
|
|
86
|
+
},
|
|
87
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { openingElementClassUtilities } from "./jsx-class-utility.js";
|
|
2
|
+
import { renderedImports } from "./rendered-import.js";
|
|
3
|
+
|
|
4
|
+
const AVATAR = "Avatar";
|
|
5
|
+
const OVERLAP = /^-(?:space-x-|ml-|ms-|mx-)/;
|
|
6
|
+
|
|
7
|
+
const hasOverlapClass = (node, context) =>
|
|
8
|
+
openingElementClassUtilities(node, context).some((utility) =>
|
|
9
|
+
OVERLAP.test(utility.slice(utility.lastIndexOf(":") + 1).replace(/^!|!$/g, "")),
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
function returnedElement(callback) {
|
|
13
|
+
if (callback?.type !== "ArrowFunctionExpression" && callback?.type !== "FunctionExpression") {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
if (callback.body.type !== "BlockStatement") return callback.body;
|
|
17
|
+
return callback.body.body.find((statement) => statement.type === "ReturnStatement")?.argument;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const noHandStackedAvatars = {
|
|
21
|
+
meta: {
|
|
22
|
+
type: "problem",
|
|
23
|
+
docs: {
|
|
24
|
+
description:
|
|
25
|
+
"Stacked avatars are one AvatarGroup, never sibling Avatars or an overlap written on a parent or an Avatar.",
|
|
26
|
+
},
|
|
27
|
+
schema: [],
|
|
28
|
+
messages: {
|
|
29
|
+
"hand-stacked-avatars":
|
|
30
|
+
"Stacked avatars are one <AvatarGroup members={...} label={...} />, which owns the overlap, the order, the +N count and the group's label.",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
create(context) {
|
|
34
|
+
const importOf = renderedImports(context);
|
|
35
|
+
const reported = new WeakSet();
|
|
36
|
+
const isAvatar = (node) =>
|
|
37
|
+
node?.type === "JSXElement" && importOf(node.openingElement.name)?.name === AVATAR;
|
|
38
|
+
|
|
39
|
+
function report(avatar) {
|
|
40
|
+
if (reported.has(avatar)) return;
|
|
41
|
+
reported.add(avatar);
|
|
42
|
+
context.report({ node: avatar.openingElement, messageId: "hand-stacked-avatars" });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
JSXElement(node) {
|
|
47
|
+
if (isAvatar(node) && hasOverlapClass(node.openingElement, context)) report(node);
|
|
48
|
+
const avatars = node.children.filter(isAvatar);
|
|
49
|
+
if (avatars.length >= 2) report(avatars[1]);
|
|
50
|
+
},
|
|
51
|
+
JSXFragment(node) {
|
|
52
|
+
const avatars = node.children.filter(isAvatar);
|
|
53
|
+
if (avatars.length >= 2) report(avatars[1]);
|
|
54
|
+
},
|
|
55
|
+
CallExpression(node) {
|
|
56
|
+
const { callee, parent } = node;
|
|
57
|
+
const isMap =
|
|
58
|
+
callee.type === "MemberExpression" && !callee.computed && callee.property.name === "map";
|
|
59
|
+
if (!isMap) return;
|
|
60
|
+
if (parent.type !== "JSXExpressionContainer" || parent.parent.type !== "JSXElement") return;
|
|
61
|
+
if (!hasOverlapClass(parent.parent.openingElement, context)) return;
|
|
62
|
+
const returned = returnedElement(node.arguments[0]);
|
|
63
|
+
if (isAvatar(returned)) report(returned);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: a `no-restricted-syntax` descendant selector
|
|
3
|
+
* matches by element name, so it cannot tell the package's Accordion from a
|
|
4
|
+
* local component of the same name, a renamed import, or a Disclosure's
|
|
5
|
+
* `label` (which is not its content) from its children.
|
|
6
|
+
*/
|
|
7
|
+
import { packageModules, partOf, renderedImports } from "./rendered-import.js";
|
|
8
|
+
|
|
9
|
+
const PARTS = [
|
|
10
|
+
["accordion", "Accordion"],
|
|
11
|
+
["accordion", "AccordionContent"],
|
|
12
|
+
["collapsible", "Collapsible"],
|
|
13
|
+
["collapsible", "CollapsibleContent"],
|
|
14
|
+
["disclosure", "Disclosure"],
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const PART_EXPORTERS = new Map(
|
|
18
|
+
PARTS.map(([module, part]) => [
|
|
19
|
+
part,
|
|
20
|
+
[...packageModules(module), `@/components/${module}`].map((from) => ({ from, part })),
|
|
21
|
+
]),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const COLLAPSES = new Set(["Accordion", "Collapsible", "Disclosure"]);
|
|
25
|
+
const COLLAPSED_CONTENT = new Set(["AccordionContent", "CollapsibleContent", "Disclosure"]);
|
|
26
|
+
|
|
27
|
+
export const noNestedCollapse = {
|
|
28
|
+
meta: {
|
|
29
|
+
type: "problem",
|
|
30
|
+
docs: {
|
|
31
|
+
description: "An Accordion, Collapsible or Disclosure never sits in another's content.",
|
|
32
|
+
},
|
|
33
|
+
schema: [],
|
|
34
|
+
messages: {
|
|
35
|
+
"nested-collapse":
|
|
36
|
+
"A collapse never sits in another: two levels hide too much and break the keyboard path. Make the inner one a section of the page, or flatten the outer.",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
create(context) {
|
|
40
|
+
const importOf = renderedImports(context);
|
|
41
|
+
const partRendered = (element) =>
|
|
42
|
+
partOf(importOf(element.openingElement.name), PART_EXPORTERS, context.filename);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
JSXElement(node) {
|
|
46
|
+
if (!COLLAPSES.has(partRendered(node))) return;
|
|
47
|
+
let child = node;
|
|
48
|
+
for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) {
|
|
49
|
+
const holdsAsContent =
|
|
50
|
+
ancestor.type === "JSXElement" && ancestor.children.includes(child);
|
|
51
|
+
if (holdsAsContent && COLLAPSED_CONTENT.has(partRendered(ancestor))) {
|
|
52
|
+
context.report({ node, messageId: "nested-collapse" });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
child = ancestor;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: a `no-restricted-syntax` descendant selector
|
|
3
|
+
* (`JSXElement[openingElement.name.name=/Form$/] JSXOpeningElement`) matches by
|
|
4
|
+
* element name, so it cannot tell the package's CollectionSearch from a local
|
|
5
|
+
* component of the same name, nor a renamed import.
|
|
6
|
+
*/
|
|
7
|
+
import { packageModules, partOf, renderedImports, writtenName } from "./rendered-import.js";
|
|
8
|
+
|
|
9
|
+
const COLLECTION_SEARCH = new Map([
|
|
10
|
+
[
|
|
11
|
+
"CollectionSearch",
|
|
12
|
+
packageModules("collection-search").map((from) => ({ from, part: "CollectionSearch" })),
|
|
13
|
+
],
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
const isForm = (element) => {
|
|
17
|
+
const name = writtenName(element.openingElement.name);
|
|
18
|
+
return name === "form" || name?.endsWith("Form") === true;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const noSearchInForm = {
|
|
22
|
+
meta: {
|
|
23
|
+
type: "problem",
|
|
24
|
+
docs: {
|
|
25
|
+
description: "A collection's search sits in its toolbar, never inside a form that saves.",
|
|
26
|
+
},
|
|
27
|
+
schema: [],
|
|
28
|
+
messages: {
|
|
29
|
+
"search-in-form":
|
|
30
|
+
"A search box does not belong in a form that saves something; a collection's search sits in its toolbar.",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
create(context) {
|
|
34
|
+
const importOf = renderedImports(context);
|
|
35
|
+
return {
|
|
36
|
+
JSXOpeningElement(node) {
|
|
37
|
+
if (partOf(importOf(node.name), COLLECTION_SEARCH, context.filename) === null) return;
|
|
38
|
+
for (let ancestor = node.parent.parent; ancestor; ancestor = ancestor.parent) {
|
|
39
|
+
if (ancestor.type === "JSXElement" && isForm(ancestor)) {
|
|
40
|
+
context.report({ node, messageId: "search-in-form" });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -21,9 +21,8 @@ import {
|
|
|
21
21
|
skipsPackageOwnedPrimitive,
|
|
22
22
|
} from "./jsx-class-utility.js";
|
|
23
23
|
|
|
24
|
-
//
|
|
25
|
-
// chooses its typed surface default
|
|
26
|
-
// Their other exports are direct reexports.
|
|
24
|
+
// This exact Portal adapter forwards props to package primitives. Card
|
|
25
|
+
// chooses its typed surface default. Its other exports are direct reexports.
|
|
27
26
|
const portalCardExports = new Set([
|
|
28
27
|
"Card",
|
|
29
28
|
"CardHeader",
|
|
@@ -32,16 +31,6 @@ const portalCardExports = new Set([
|
|
|
32
31
|
"CardAction",
|
|
33
32
|
"CardContent",
|
|
34
33
|
]);
|
|
35
|
-
const portalTableExports = new Set([
|
|
36
|
-
"Table",
|
|
37
|
-
"TableHead",
|
|
38
|
-
"TableCell",
|
|
39
|
-
"TableBody",
|
|
40
|
-
"TableCaption",
|
|
41
|
-
"TableFooter",
|
|
42
|
-
"TableHeader",
|
|
43
|
-
"TableRow",
|
|
44
|
-
]);
|
|
45
34
|
|
|
46
35
|
function primitiveModule(source, filename) {
|
|
47
36
|
if (source.startsWith("@nadicodeai/ui/components/")) {
|
|
@@ -57,9 +46,6 @@ function primitiveModule(source, filename) {
|
|
|
57
46
|
if (source === "@/components/kit/card" || resolved === `${portalSource}/components/kit/card`) {
|
|
58
47
|
return { card: true, exports: portalCardExports };
|
|
59
48
|
}
|
|
60
|
-
if (source === "@/components/kit/table" || resolved === `${portalSource}/components/kit/table`) {
|
|
61
|
-
return { card: false, exports: portalTableExports };
|
|
62
|
-
}
|
|
63
49
|
return undefined;
|
|
64
50
|
}
|
|
65
51
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A Snippet draws its own prompt and copies only the command, so a `$ ` or `> `
|
|
3
|
+
* typed into `text` shows twice and is on the clipboard.
|
|
4
|
+
*
|
|
5
|
+
* Standard tool checked first: `no-restricted-syntax` can match a string
|
|
6
|
+
* starting with `$ `, but not whether it is the `text` of the package's Snippet
|
|
7
|
+
* (an import binding, so a renamed or local `Snippet` is judged correctly),
|
|
8
|
+
* and it cannot read the items of an array or exempt `prompt={false}`.
|
|
9
|
+
*/
|
|
10
|
+
import { partOf, renderedImports, staticAttribute } from "./rendered-import.js";
|
|
11
|
+
|
|
12
|
+
const SNIPPET = new Map([
|
|
13
|
+
[
|
|
14
|
+
"Snippet",
|
|
15
|
+
[
|
|
16
|
+
{ from: "@nadicodeai/ui/components/snippet", part: "Snippet" },
|
|
17
|
+
{ from: "@nadicodeai/ui", part: "Snippet" },
|
|
18
|
+
],
|
|
19
|
+
],
|
|
20
|
+
]);
|
|
21
|
+
const OWNER_FILE = "packages/ui/src/components/snippet.tsx";
|
|
22
|
+
|
|
23
|
+
const startsWithPrompt = (text) => text === "$" || text.startsWith("$ ") || text.startsWith("> ");
|
|
24
|
+
|
|
25
|
+
function writtenText(node) {
|
|
26
|
+
// oxlint-disable-next-line anti-slop/no-runtime-typeof -- ESTree types Literal.value as string | number | boolean | RegExp | bigint | null; only typeof picks the string.
|
|
27
|
+
if (node.type === "Literal") return typeof node.value === "string" ? node.value : null;
|
|
28
|
+
if (node.type === "TemplateLiteral" && node.expressions.length === 0) {
|
|
29
|
+
return node.quasis[0].value.cooked;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function promptedItems(value) {
|
|
35
|
+
if (!value) return [];
|
|
36
|
+
const written = value.type === "JSXExpressionContainer" ? value.expression : value;
|
|
37
|
+
const items = written.type === "ArrayExpression" ? written.elements : [written];
|
|
38
|
+
return items.filter((item) => {
|
|
39
|
+
if (!item || item.type === "SpreadElement") return false;
|
|
40
|
+
const text = writtenText(item);
|
|
41
|
+
return text !== null && startsWithPrompt(text);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const noShellPromptInSnippet = {
|
|
46
|
+
meta: {
|
|
47
|
+
type: "problem",
|
|
48
|
+
docs: {
|
|
49
|
+
description: "A Snippet's text never starts with the prompt the Snippet draws.",
|
|
50
|
+
},
|
|
51
|
+
schema: [],
|
|
52
|
+
messages: {
|
|
53
|
+
"typed-prompt":
|
|
54
|
+
'The Snippet draws the prompt. Remove the leading "$ " from text, or pass prompt={false} when the value is not a shell command.',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
create(context) {
|
|
58
|
+
if (context.filename.replaceAll("\\", "/").endsWith(`/${OWNER_FILE}`)) return {};
|
|
59
|
+
const importOf = renderedImports(context);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
JSXOpeningElement(node) {
|
|
63
|
+
if (partOf(importOf(node.name), SNIPPET, context.filename) !== "Snippet") return;
|
|
64
|
+
if (staticAttribute(node, "prompt") === false) return;
|
|
65
|
+
const text = node.attributes.find(
|
|
66
|
+
(attribute) => attribute.type === "JSXAttribute" && attribute.name.name === "text",
|
|
67
|
+
);
|
|
68
|
+
for (const item of promptedItems(text?.value)) {
|
|
69
|
+
context.report({ node: item, messageId: "typed-prompt" });
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: `no-restricted-syntax` matches a string by one
|
|
3
|
+
* regular expression per selector and would need one entry per phrase and per
|
|
4
|
+
* node kind (a literal, a template's text, JSX text); one rule lists the
|
|
5
|
+
* phrases once and reads them in the catalogue files only, by path.
|
|
6
|
+
*/
|
|
7
|
+
import { literalText } from "./literal-text.js";
|
|
8
|
+
|
|
9
|
+
const PHRASES = [
|
|
10
|
+
["Something went wrong", /\bsomething went wrong\b/i],
|
|
11
|
+
["Unable to", /\bunable to\b/i],
|
|
12
|
+
["Heads up", /\bheads[ -]up\b/i],
|
|
13
|
+
["please", /\bplease\b/i],
|
|
14
|
+
["successfully", /\bsuccessfully\b/i],
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const CATALOGUE_FILE = /(?:^|\/)(?:copy|i18n)\/|(?:^|\/)(?:words|messages)\.[jt]s$/;
|
|
18
|
+
const TEST_FILE = /\.test\.[jt]sx?$/;
|
|
19
|
+
|
|
20
|
+
export const noStockErrorWords = {
|
|
21
|
+
meta: {
|
|
22
|
+
type: "problem",
|
|
23
|
+
docs: {
|
|
24
|
+
description:
|
|
25
|
+
'A catalogue message never says "Something went wrong", "Unable to", "Heads up", "please" or "successfully".',
|
|
26
|
+
},
|
|
27
|
+
schema: [],
|
|
28
|
+
messages: {
|
|
29
|
+
"stock-phrase":
|
|
30
|
+
'A catalogue message does not say "{{phrase}}": name what happened to which record and what the person can do, in the active voice ("Couldn\'t pause Discord. The Gateway didn\'t answer."), with no please and no "successfully".',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
create(context) {
|
|
34
|
+
const filename = context.filename.replaceAll("\\", "/");
|
|
35
|
+
if (!CATALOGUE_FILE.test(filename) || TEST_FILE.test(filename)) return {};
|
|
36
|
+
|
|
37
|
+
function check(node, text) {
|
|
38
|
+
if (text === null) return;
|
|
39
|
+
for (const [phrase, pattern] of PHRASES) {
|
|
40
|
+
if (pattern.test(text))
|
|
41
|
+
context.report({ node, messageId: "stock-phrase", data: { phrase } });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
Literal(node) {
|
|
47
|
+
if (node.parent.type === "ImportDeclaration" || node.parent.type === "ExportAllDeclaration")
|
|
48
|
+
return;
|
|
49
|
+
check(node, literalText(node));
|
|
50
|
+
},
|
|
51
|
+
TemplateElement(node) {
|
|
52
|
+
check(node, node.value.cooked);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: a `no-restricted-syntax` selector can match a
|
|
3
|
+
* `Field` descendant of a `Tooltip` by element name, but not that both are
|
|
4
|
+
* imports from the design system, nor reach a field named in the `render`
|
|
5
|
+
* element of a trigger, so it would also refuse a product's own `Input`.
|
|
6
|
+
*/
|
|
7
|
+
import { renderedImports, walk } from "./rendered-import.js";
|
|
8
|
+
|
|
9
|
+
const WRAPPERS = new Set(["Tooltip", "TooltipTrigger", "HoverCard", "HoverCardTrigger"]);
|
|
10
|
+
const POPUPS = new Set(["TooltipContent", "HoverCardContent"]);
|
|
11
|
+
const FIELDS = new Set([
|
|
12
|
+
"Input",
|
|
13
|
+
"Textarea",
|
|
14
|
+
"ClearableInput",
|
|
15
|
+
"CollectionSearch",
|
|
16
|
+
"Select",
|
|
17
|
+
"SelectTrigger",
|
|
18
|
+
"NativeSelect",
|
|
19
|
+
"Combobox",
|
|
20
|
+
"ComboboxInput",
|
|
21
|
+
"Checkbox",
|
|
22
|
+
"Switch",
|
|
23
|
+
"Label",
|
|
24
|
+
"FieldLabel",
|
|
25
|
+
"SettingsField",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
const FROM_DESIGN_SYSTEM = /^(@nadicodeai\/ui(\/|$)|@\/|\.)/;
|
|
29
|
+
|
|
30
|
+
export const noTooltipAroundLabelledField = {
|
|
31
|
+
meta: {
|
|
32
|
+
type: "problem",
|
|
33
|
+
docs: {
|
|
34
|
+
description:
|
|
35
|
+
"A Tooltip or HoverCard never wraps a field: put the help on an icon button beside it.",
|
|
36
|
+
},
|
|
37
|
+
schema: [],
|
|
38
|
+
messages: {
|
|
39
|
+
"field-tooltip":
|
|
40
|
+
"Do not put a Tooltip or HoverCard on a field: its text becomes a second, hidden label. Put the help on an icon button beside the field.",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
create(context) {
|
|
44
|
+
const importOf = renderedImports(context);
|
|
45
|
+
const exportOf = (elementName) => {
|
|
46
|
+
const imported = importOf(elementName);
|
|
47
|
+
return imported && FROM_DESIGN_SYSTEM.test(imported.source) ? imported.name : null;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
function wrapsAField(element) {
|
|
51
|
+
let found = false;
|
|
52
|
+
walk(element, context.sourceCode.visitorKeys, (child) => {
|
|
53
|
+
if (child.type !== "JSXElement") return true;
|
|
54
|
+
const name = exportOf(child.openingElement.name);
|
|
55
|
+
if (POPUPS.has(name)) return false;
|
|
56
|
+
if (!FIELDS.has(name)) return true;
|
|
57
|
+
found = true;
|
|
58
|
+
return "stop";
|
|
59
|
+
});
|
|
60
|
+
return found;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
JSXElement(node) {
|
|
65
|
+
if (!WRAPPERS.has(exportOf(node.openingElement.name))) return;
|
|
66
|
+
if (wrapsAField(node)) {
|
|
67
|
+
context.report({ node: node.openingElement, messageId: "field-tooltip" });
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: a `no-restricted-syntax` selector can match a
|
|
3
|
+
* `strong` whose own className holds a weight class, but cannot ask whether some
|
|
4
|
+
* element above it carries a type role, so it would refuse every weighted
|
|
5
|
+
* `<strong>` or none. This rule reads both classNames, ancestors included, in
|
|
6
|
+
* one file.
|
|
7
|
+
*/
|
|
8
|
+
import { openingElementClassUtilities } from "./jsx-class-utility.js";
|
|
9
|
+
|
|
10
|
+
const STRONG_TAGS = new Set(["strong", "b"]);
|
|
11
|
+
const WEIGHT_CLASS = /^font-(medium|semibold|bold)$/;
|
|
12
|
+
const TYPE_ROLE_CLASS = /^(nc-type-|text-(display-|heading-|body-|label|caption))/;
|
|
13
|
+
|
|
14
|
+
const baseUtility = (utility) => utility.slice(utility.lastIndexOf(":") + 1).replace(/^!/, "");
|
|
15
|
+
|
|
16
|
+
const hasUtility = (element, context, pattern) =>
|
|
17
|
+
openingElementClassUtilities(element, context).some((utility) =>
|
|
18
|
+
pattern.test(baseUtility(utility)),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
function hasTypeRoleAncestor(element, context) {
|
|
22
|
+
for (let ancestor = element.parent?.parent; ancestor; ancestor = ancestor.parent) {
|
|
23
|
+
if (
|
|
24
|
+
ancestor.type === "JSXElement" &&
|
|
25
|
+
hasUtility(ancestor.openingElement, context, TYPE_ROLE_CLASS)
|
|
26
|
+
) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const noWeightClassOnStrongInTypeRole = {
|
|
34
|
+
meta: {
|
|
35
|
+
type: "problem",
|
|
36
|
+
docs: {
|
|
37
|
+
description:
|
|
38
|
+
"A type role sets the weight of a nested <strong>; the element carries no weight class.",
|
|
39
|
+
},
|
|
40
|
+
schema: [],
|
|
41
|
+
messages: {
|
|
42
|
+
"weight-on-strong":
|
|
43
|
+
"The type role sets the weight of a nested <strong>: 550 in copy, 500 in labels and headings. Remove the font-weight class from the <strong>.",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
create(context) {
|
|
47
|
+
return {
|
|
48
|
+
JSXOpeningElement(node) {
|
|
49
|
+
if (node.name.type !== "JSXIdentifier" || !STRONG_TAGS.has(node.name.name)) return;
|
|
50
|
+
if (!hasUtility(node, context, WEIGHT_CLASS)) return;
|
|
51
|
+
if (hasTypeRoleAncestor(node, context)) {
|
|
52
|
+
context.report({ node, messageId: "weight-on-strong" });
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: a `no-restricted-syntax` descendant selector
|
|
3
|
+
* matches by element name, so it cannot tell the package's
|
|
4
|
+
* `DropdownMenuSub` from a local component of the same name or follow a
|
|
5
|
+
* renamed import.
|
|
6
|
+
*/
|
|
7
|
+
import { renderedImports } from "./rendered-import.js";
|
|
8
|
+
|
|
9
|
+
const SUBMENUS = new Set(["DropdownMenuSub", "ContextMenuSub", "MenubarSub"]);
|
|
10
|
+
const FROM_DESIGN_SYSTEM = /^(@nadicodeai\/ui(\/|$)|@\/|\.)/;
|
|
11
|
+
|
|
12
|
+
export const oneSubmenuLevel = {
|
|
13
|
+
meta: {
|
|
14
|
+
type: "problem",
|
|
15
|
+
docs: { description: "A menu has one level of submenu, never a submenu inside a submenu." },
|
|
16
|
+
schema: [],
|
|
17
|
+
messages: {
|
|
18
|
+
"nested-submenu":
|
|
19
|
+
"A menu opens one submenu deep. A third level hides commands behind a pointer path that is easy to lose: flatten the inner submenu into a group of the first, or move it to its own menu.",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
create(context) {
|
|
23
|
+
const importOf = renderedImports(context);
|
|
24
|
+
const isSubmenu = (element) => {
|
|
25
|
+
const imported = importOf(element.openingElement.name);
|
|
26
|
+
return (
|
|
27
|
+
imported !== null && SUBMENUS.has(imported.name) && FROM_DESIGN_SYSTEM.test(imported.source)
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
JSXElement(node) {
|
|
33
|
+
if (!isSubmenu(node)) return;
|
|
34
|
+
for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) {
|
|
35
|
+
if (ancestor.type === "JSXElement" && isSubmenu(ancestor)) {
|
|
36
|
+
context.report({ node: node.openingElement, messageId: "nested-submenu" });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
};
|