ropav 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/ancestry.js +136 -0
- package/dist/calendar.css +184 -0
- package/dist/calendar.js +739 -0
- package/dist/calendar2.js +37 -0
- package/dist/chevron-left.js +12 -0
- package/dist/color-picker.js +38 -88
- package/dist/combobox.css +251 -0
- package/dist/combobox.js +410 -0
- package/dist/components/calendar/calendar.d.ts +30 -0
- package/dist/components/calendar/calendarBehavior.d.ts +49 -0
- package/dist/components/calendar/index.d.ts +3 -0
- package/dist/components/calendar/index.js +3 -0
- package/dist/components/calendar/types.d.ts +56 -0
- package/dist/components/calendar/useCalendar.d.ts +24 -0
- package/dist/components/color-picker/useColorPickerDrag.d.ts +1 -1
- package/dist/components/color-picker/useColorPickerSaturation.d.ts +1 -1
- package/dist/components/color-picker/useColorPickerSlider.d.ts +1 -1
- package/dist/components/combobox/combobox.d.ts +29 -0
- package/dist/components/combobox/comboboxModel.d.ts +4 -0
- package/dist/components/combobox/index.d.ts +3 -0
- package/dist/components/combobox/index.js +2 -0
- package/dist/components/combobox/types.d.ts +43 -0
- package/dist/components/combobox/useCombobox.d.ts +45 -0
- package/dist/components/date-picker/date-picker.d.ts +33 -0
- package/dist/components/date-picker/datePickerModel.d.ts +10 -0
- package/dist/components/date-picker/index.d.ts +4 -0
- package/dist/components/date-picker/index.js +2 -0
- package/dist/components/date-picker/types.d.ts +59 -0
- package/dist/components/date-picker/useDatePicker.d.ts +29 -0
- package/dist/components/date-picker/useDatePickerValueState.d.ts +21 -0
- package/dist/components/dropdown-menu/dropdown-menu-content.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu-sub-content.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdownMenuContext.d.ts +7 -18
- package/dist/components/dropdown-menu/dropdownMenuInteraction.d.ts +3 -3
- package/dist/components/dropdown-menu/dropdownMenuInteractionTypes.d.ts +58 -29
- package/dist/components/dropdown-menu/useDropdownMenuDataController.d.ts +4 -3
- package/dist/components/dropdown-menu/useDropdownMenuDataRegistration.d.ts +6 -4
- package/dist/components/dropdown-menu/useDropdownMenuPresentation.d.ts +3 -4
- package/dist/components/dropdown-menu/useDropdownMenuTargetBindings.d.ts +5 -5
- package/dist/components/dropzone/dropzone.d.ts +31 -0
- package/dist/components/dropzone/dropzoneModel.d.ts +16 -0
- package/dist/components/dropzone/index.d.ts +3 -0
- package/dist/components/dropzone/index.js +2 -0
- package/dist/components/dropzone/types.d.ts +56 -0
- package/dist/components/dropzone/useDropzone.d.ts +25 -0
- package/dist/components/file-input/file-input.d.ts +29 -0
- package/dist/components/file-input/index.d.ts +3 -0
- package/dist/components/file-input/index.js +2 -0
- package/dist/components/file-input/types.d.ts +37 -0
- package/dist/components/file-input/useFileInput.d.ts +15 -0
- package/dist/components/floating/index.js +1 -1
- package/dist/components/floating/useFloatingPosition.d.ts +1 -13
- package/dist/components/floating/useFloatingTargetLifecycle.d.ts +32 -0
- package/dist/components/floating/useHoverDisclosure.d.ts +10 -0
- package/dist/components/hover-card/hover-card.d.ts +25 -0
- package/dist/components/hover-card/index.d.ts +3 -0
- package/dist/components/hover-card/index.js +2 -0
- package/dist/components/hover-card/types.d.ts +45 -0
- package/dist/components/hover-card/useHoverCard.d.ts +22 -0
- package/dist/components/hover-card/useHoverCardDisclosure.d.ts +19 -0
- package/dist/components/multi-select/index.d.ts +3 -0
- package/dist/components/multi-select/index.js +2 -0
- package/dist/components/multi-select/multi-select.d.ts +30 -0
- package/dist/components/multi-select/multiSelectModel.d.ts +3 -0
- package/dist/components/multi-select/types.d.ts +49 -0
- package/dist/components/multi-select/useMultiSelect.d.ts +46 -0
- package/dist/components/number-input/useNumberInput.d.ts +1 -3
- package/dist/components/popover/usePopoverBindings.d.ts +3 -6
- package/dist/components/scroll-area/useScrollArea.d.ts +4 -4
- package/dist/components/scroll-area/useScrollAreaAttributes.d.ts +3 -3
- package/dist/components/scroll-area/useScrollAreaPointer.d.ts +1 -1
- package/dist/components/segmented-control/index.d.ts +3 -0
- package/dist/components/segmented-control/index.js +2 -0
- package/dist/components/segmented-control/segmented-control.d.ts +26 -0
- package/dist/components/segmented-control/types.d.ts +47 -0
- package/dist/components/segmented-control/useSegmentedControl.d.ts +15 -0
- package/dist/components/select/useSelect.d.ts +31 -19
- package/dist/components/slider/useRangeSlider.d.ts +1 -1
- package/dist/components/slider/useRangeSliderPointer.d.ts +1 -1
- package/dist/components/slider/useSlider.d.ts +1 -1
- package/dist/components/slider/useSliderPointer.d.ts +15 -0
- package/dist/components/slider/useSliderValueState.d.ts +1 -0
- package/dist/components/tags-input/index.d.ts +3 -0
- package/dist/components/tags-input/index.js +2 -0
- package/dist/components/tags-input/tags-input.d.ts +27 -0
- package/dist/components/tags-input/tagsInputModel.d.ts +12 -0
- package/dist/components/tags-input/types.d.ts +37 -0
- package/dist/components/tags-input/useTagsInput.d.ts +23 -0
- package/dist/components/toolbar/index.d.ts +3 -0
- package/dist/components/toolbar/index.js +2 -0
- package/dist/components/toolbar/toolbar.d.ts +24 -0
- package/dist/components/toolbar/types.d.ts +12 -0
- package/dist/components/toolbar/useToolbar.d.ts +7 -0
- package/dist/components/tooltip/useTooltipTargetBindings.d.ts +12 -0
- package/dist/date-picker.css +49 -0
- package/dist/date-picker.js +811 -0
- package/dist/dialog.js +9 -20
- package/dist/direction.js +6 -0
- package/dist/dropdown-menu.css +21 -3
- package/dist/dropdown-menu.js +341 -261
- package/dist/dropzone.css +135 -0
- package/dist/dropzone.js +431 -0
- package/dist/file-input.css +135 -0
- package/dist/file-input.js +198 -0
- package/dist/focusNavigation.js +12 -6
- package/dist/hover-card.css +80 -0
- package/dist/hover-card.js +402 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +15 -3
- package/dist/internal/composables/useOverlayLayer.d.ts +12 -0
- package/dist/modal.js +1 -1
- package/dist/multi-select.css +316 -0
- package/dist/multi-select.js +481 -0
- package/dist/nativeChoice.js +169 -0
- package/dist/number-input.css +18 -18
- package/dist/number-input.js +36 -38
- package/dist/pagination.js +1 -10
- package/dist/pointerSession.js +130 -0
- package/dist/popover.css +21 -3
- package/dist/popover.js +37 -62
- package/dist/scroll-area.js +52 -62
- package/dist/segmented-control.css +176 -0
- package/dist/segmented-control.js +382 -0
- package/dist/select.css +50 -48
- package/dist/select.js +121 -271
- package/dist/slider.css +78 -69
- package/dist/slider.js +161 -145
- package/dist/tags-input.css +197 -0
- package/dist/tags-input.js +380 -0
- package/dist/toolbar.css +15 -0
- package/dist/toolbar.js +143 -0
- package/dist/tooltip.js +35 -30
- package/dist/useEditableOptionList.js +216 -0
- package/dist/useFlatOptionCollection.js +134 -0
- package/dist/useFloatingPosition.js +4 -160
- package/dist/useFloatingTargetLifecycle.js +127 -0
- package/dist/useFormControl.js +1 -0
- package/dist/{floating.js → useHoverDisclosure.js} +338 -421
- package/dist/useNativeChoiceTransaction.js +46 -0
- package/dist/useNativeFileSelection.js +86 -0
- package/dist/useOverlayZIndex.js +246 -15
- package/dist/utils/date.d.ts +13 -0
- package/dist/utils/dateAvailability.d.ts +7 -0
- package/dist/utils/dom/ancestry.d.ts +1 -0
- package/dist/utils/dom/direction.d.ts +2 -0
- package/dist/utils/dom/files.d.ts +3 -0
- package/dist/utils/dom/focusNavigation.d.ts +4 -1
- package/dist/utils/dom/nativeChoice.d.ts +17 -0
- package/dist/utils/dom/pointerSession.d.ts +20 -0
- package/dist/utils/dom/scroll.d.ts +2 -1
- package/dist/utils/optionFilter.d.ts +5 -0
- package/docs/public-floating-api.md +7 -4
- package/docs/public-styles-api.md +28 -12
- package/package.json +68 -40
- package/src/styles/_mixins.scss +26 -0
- package/src/styles/styles-manifest.json +1 -2
- package/dist/components/floating/hoverDisclosureInteractionModel.d.ts +0 -42
- package/dist/components/floating/useHoverDisclosureInteractions.d.ts +0 -32
- package/dist/components/floating/useHoverDisclosureOpenState.d.ts +0 -25
- package/dist/components/floating/useHoverDisclosureTargetBinding.d.ts +0 -27
- package/dist/components/select/useSelectNativeControl.d.ts +0 -9
- package/dist/components/select/useSelectNativeValue.d.ts +0 -9
- package/dist/pointer.js +0 -9
- package/dist/utils/dom/pointer.d.ts +0 -2
- package/docs/code-architecture.md +0 -118
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public Styles API
|
|
2
2
|
|
|
3
|
-
The Public Styles API is the supported way to restyle Ropav without depending on component DOM nesting or internal selectors.
|
|
3
|
+
The Public Styles API is the supported way to restyle Ropav without depending on component DOM nesting or internal selectors.
|
|
4
4
|
|
|
5
5
|
## Typed component API
|
|
6
6
|
|
|
@@ -46,57 +46,71 @@ Only independently useful semantic elements are public parts. Conditional parts
|
|
|
46
46
|
| Button, ButtonLink | `root`, `loader`, `left`, `label`, `right` |
|
|
47
47
|
| IconButton | `root`, `loader`, `icon` |
|
|
48
48
|
| ButtonGroup | `root` |
|
|
49
|
+
| Calendar | `root`, `header`, `previousControl`, `monthLabel`, `nextControl`, `weekdays`, `weekday`, `grid`, `week`, `dayCell`, `day` |
|
|
49
50
|
| Card | `root`, `header`, `title`, `description`, `body`, `footer` |
|
|
50
51
|
| Checkbox | `root`, `input`, `indicator`, `label` |
|
|
51
52
|
| Collapse | `root`, `trigger`, `content` |
|
|
52
53
|
| ColorInput | `root`, `control`, `input`, `preview`, `eyeDropper`, `content`, `picker`, `pickerControl`, `pickerHandle`, `pickerSwatches`, `pickerSwatch` |
|
|
53
54
|
| ColorPicker | `root`, `label`, `control`, `handle`, `swatches`, `swatch` |
|
|
54
55
|
| ColorSwatch | `root` |
|
|
56
|
+
| Combobox | `root`, `input`, `indicator`, `clear`, `toggle`, `content`, `option`, `empty` |
|
|
55
57
|
| DropdownMenu | `root`, `trigger`, `content`, `item`, `label`, `shortcut`, `submenu`, `submenuIndicator`, `empty` |
|
|
58
|
+
| Dropzone | `root`, `input`, `content`, `label`, `description` |
|
|
56
59
|
| Field | `root`, `label`, `required`, `control`, `description` |
|
|
60
|
+
| FileInput | `root`, `input`, `trigger`, `value` |
|
|
57
61
|
| FocusTrap | `root` |
|
|
58
62
|
| Input | `root`, `input`, `left`, `right` |
|
|
59
63
|
| Modal | `root`, `overlay`, `panel`, `header`, `title`, `description`, `body`, `footer`, `close` |
|
|
64
|
+
| MultiSelect | `root`, `pills`, `pill`, `pillLabel`, `pillRemove`, `input`, `indicator`, `clear`, `toggle`, `content`, `option`, `empty` |
|
|
60
65
|
| NumberInput | `root`, `input`, `control` |
|
|
61
66
|
| Overlay | `root` |
|
|
62
|
-
| Popover, Tooltip
|
|
67
|
+
| HoverCard, Popover, Tooltip | `root`, `trigger`, `content` |
|
|
63
68
|
| Progress | `root`, `label`, `value`, `track`, `indicator` |
|
|
64
69
|
| Radio | `root`, `input`, `indicator`, `label` |
|
|
65
70
|
| RadioGroup | `root` |
|
|
71
|
+
| SegmentedControl | `root`, `control`, `input`, `indicator`, `label` |
|
|
66
72
|
| Select | `root`, `trigger`, `value`, `indicator`, `clear`, `content`, `option`, `empty` |
|
|
67
73
|
| Slider | `root`, `label`, `value`, `track`, `range`, `input`, `thumb`, `mark`, `markLabel`, `tooltip` |
|
|
68
74
|
| RangeSlider | `root`, `label`, `value`, `track`, `range`, `input`, `thumb`, `mark`, `markLabel`, `tooltip` |
|
|
69
75
|
| Switch | `root`, `input`, `track`, `thumb`, `label` |
|
|
70
76
|
| Tabs, TabsList, TabsTrigger, TabsContent | `root` on each component |
|
|
77
|
+
| TagsInput | `root`, `tags`, `tag`, `tagLabel`, `tagRemove`, `input`, `clear` |
|
|
71
78
|
| Textarea | `root`, `input` |
|
|
72
79
|
| Toast | `root`, `icon`, `title`, `description`, `body`, `action`, `close` |
|
|
73
80
|
| ToastViewport | `root`, `item`, `toast`, `toastIcon`, `toastTitle`, `toastDescription`, `toastBody`, `toastAction`, `toastClose` |
|
|
74
81
|
|
|
75
82
|
`ToastProvider` renders no DOM and therefore has no Styles API.
|
|
76
83
|
|
|
84
|
+
When `Calendar.showHeader` is `false`, the `header`, `previousControl` and `nextControl` parts are
|
|
85
|
+
not rendered. The `monthLabel` part remains as a visually hidden live label for the calendar grid.
|
|
86
|
+
|
|
77
87
|
## State attributes
|
|
78
88
|
|
|
79
89
|
Boolean states use presence semantics: the attribute value is empty when true and the attribute is absent when false or unknown. Enum values are lowercase kebab-case.
|
|
80
90
|
|
|
81
|
-
- `data-state="open|closed"`: AccordionItem, Collapse, DropdownMenu and submenus, Modal, Popover, Select and Tooltip.
|
|
91
|
+
- `data-state="open|closed"`: AccordionItem, Collapse, Combobox, DropdownMenu and submenus, HoverCard, Modal, MultiSelect, Popover, Select and Tooltip.
|
|
82
92
|
- `data-state="checked|unchecked|indeterminate"`: Checkbox.
|
|
83
|
-
- `data-state="checked|unchecked"`: Radio and Switch.
|
|
93
|
+
- `data-state="checked|unchecked"`: Radio, SegmentedControl controls and inputs, and Switch.
|
|
84
94
|
- `data-state="active|inactive"`: TabsTrigger and TabsContent.
|
|
85
95
|
- `data-state="determinate|indeterminate"`: Progress.
|
|
96
|
+
- `data-state="idle|accept|reject"`: Dropzone.
|
|
86
97
|
- `data-disabled`: the effective disabled state on each applicable control, trigger, item or option.
|
|
87
|
-
- `data-readonly`: Input, Textarea, ColorInput and ColorPicker controls.
|
|
98
|
+
- `data-readonly`: Calendar, Input, Textarea, TagsInput, ColorInput and ColorPicker controls.
|
|
88
99
|
- `data-invalid`: form-control roots and their public input parts.
|
|
89
100
|
- `data-loading`: Button, ButtonLink and IconButton.
|
|
90
101
|
- `data-active` and `data-paused`: FocusTrap.
|
|
91
|
-
- `data-selected`: Select options and ColorPicker swatches.
|
|
92
|
-
- `data-
|
|
102
|
+
- `data-selected`: Calendar days, Combobox, MultiSelect and Select options, and ColorPicker swatches.
|
|
103
|
+
- `data-outside` and `data-today`: Calendar days.
|
|
104
|
+
- `data-month="YYYY-MM-DD"`: Calendar roots.
|
|
105
|
+
- `data-highlighted`: Combobox, MultiSelect and Select options, and DropdownMenu items.
|
|
93
106
|
- `data-filled`: Slider and RangeSlider marks.
|
|
107
|
+
- `data-filled` and `data-dragging`: Dropzone.
|
|
94
108
|
- `data-track-hovered` and `data-dragging`: Slider track pointer interaction.
|
|
95
109
|
- `data-thumb-visibility="always|interaction|hidden"`: Slider thumb visibility behavior.
|
|
96
110
|
- `data-submenu`: DropdownMenu items that own children.
|
|
97
|
-
- `data-orientation="horizontal|vertical"`: ButtonGroup, RadioGroup, Slider, RangeSlider, Tabs and TabsList.
|
|
98
|
-
- `data-placement`: the final placement after collision handling; twelve placements for Popover and DropdownMenu, and a side (`top`, `right`, `bottom`, `left`) for Tooltip.
|
|
99
|
-
- `data-side="top|right|bottom|left"`: the side component of the final placement for Popover, DropdownMenu and Tooltip.
|
|
111
|
+
- `data-orientation="horizontal|vertical"`: ButtonGroup, RadioGroup, SegmentedControl, Slider, RangeSlider, Tabs and TabsList.
|
|
112
|
+
- `data-placement`: the final placement after collision handling; twelve placements for HoverCard, Popover and DropdownMenu, `top-start|bottom-start` for Combobox, MultiSelect and Select, and a side (`top`, `right`, `bottom`, `left`) for Tooltip.
|
|
113
|
+
- `data-side="top|right|bottom|left"`: the side component of the final placement for Combobox, MultiSelect, HoverCard, Popover, DropdownMenu, Select and Tooltip.
|
|
100
114
|
- `data-control="increment|decrement"`: NumberInput controls.
|
|
101
115
|
- `data-control="saturation|hue|opacity"`: ColorPicker controls and handles.
|
|
102
116
|
- `data-thumb="lower|upper|merged"`: RangeSlider inputs, thumbs and tooltips; `data-active-thumb="lower|upper"` is present on its root only while a thumb is active.
|
|
@@ -111,6 +125,8 @@ The exact entries in [`styles-manifest.json`](../src/styles/styles-manifest.json
|
|
|
111
125
|
|
|
112
126
|
The manifest contains design tokens plus a deliberately small component-geometry allowlist. Slider and RangeSlider share the `--rp-slider-*` namespace. Size presets provide fallbacks, while a consumer value wins for the individual dimension. See the generated [token table](./public-tokens.md).
|
|
113
127
|
|
|
128
|
+
The schema-v2 manifest does not pin a Git commit. `tokens:check` resolves compatibility from release tags, so the baseline advances with releases instead of remaining hard-coded.
|
|
129
|
+
|
|
114
130
|
Palette shades and their normal and active `*-contrast` companions are required override groups because `autoContrast` consumes state-specific companions selected at build time. The [color override contract](./public-tokens.md#color-override-contract) documents the state pairings and preset-role requirements.
|
|
115
131
|
|
|
116
132
|
## Cascade layers and migration
|
|
@@ -128,6 +144,6 @@ Place global resets in `reset` and application overrides in `app`. Import order
|
|
|
128
144
|
- Typed parts, state attributes, manifest entries, geometry variables and cascade layers form the current Public Styles API.
|
|
129
145
|
- Renaming or removing a documented part, state attribute or variable changes the public contract.
|
|
130
146
|
- Adding a public part, state attribute or variable extends the public contract.
|
|
131
|
-
- `tokens:check` compares the current manifest with the latest reachable `
|
|
132
|
-
- Release tags must be available in the Git checkout that runs the check. `PUBLIC_STYLES_BASELINE_REF` can explicitly
|
|
147
|
+
- `tokens:check` compares the current manifest with the latest reachable `ropav@*` release tag that contains one. Until the first package-specific release exists, it falls back to legacy `v*` tags and their pre-monorepo manifest path. Released variables cannot be removed, renamed or changed semantically; adding a variable requires incrementing the manifest's `contractVersion`.
|
|
148
|
+
- Release tags must be available in the Git checkout that runs the check. `PUBLIC_STYLES_BASELINE_REF` can explicitly select another Git ref that contains a manifest.
|
|
133
149
|
- Internal DOM, selectors and undocumented variables are outside the public contract.
|
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ropav",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"packageManager": "pnpm@11.15.1",
|
|
7
6
|
"engines": {
|
|
8
7
|
"node": "^20.19.0 || ^22.13.0 || >=24.0.0"
|
|
9
8
|
},
|
|
@@ -65,6 +64,10 @@
|
|
|
65
64
|
"types": "./dist/components/button-link/index.d.ts",
|
|
66
65
|
"import": "./dist/components/button-link/index.js"
|
|
67
66
|
},
|
|
67
|
+
"./calendar": {
|
|
68
|
+
"types": "./dist/components/calendar/index.d.ts",
|
|
69
|
+
"import": "./dist/components/calendar/index.js"
|
|
70
|
+
},
|
|
68
71
|
"./card": {
|
|
69
72
|
"types": "./dist/components/card/index.d.ts",
|
|
70
73
|
"import": "./dist/components/card/index.js"
|
|
@@ -89,6 +92,14 @@
|
|
|
89
92
|
"types": "./dist/components/color-swatch/index.d.ts",
|
|
90
93
|
"import": "./dist/components/color-swatch/index.js"
|
|
91
94
|
},
|
|
95
|
+
"./combobox": {
|
|
96
|
+
"types": "./dist/components/combobox/index.d.ts",
|
|
97
|
+
"import": "./dist/components/combobox/index.js"
|
|
98
|
+
},
|
|
99
|
+
"./date-picker": {
|
|
100
|
+
"types": "./dist/components/date-picker/index.d.ts",
|
|
101
|
+
"import": "./dist/components/date-picker/index.js"
|
|
102
|
+
},
|
|
92
103
|
"./dialog": {
|
|
93
104
|
"types": "./dist/components/dialog/index.d.ts",
|
|
94
105
|
"import": "./dist/components/dialog/index.js"
|
|
@@ -97,10 +108,18 @@
|
|
|
97
108
|
"types": "./dist/components/dropdown-menu/index.d.ts",
|
|
98
109
|
"import": "./dist/components/dropdown-menu/index.js"
|
|
99
110
|
},
|
|
111
|
+
"./dropzone": {
|
|
112
|
+
"types": "./dist/components/dropzone/index.d.ts",
|
|
113
|
+
"import": "./dist/components/dropzone/index.js"
|
|
114
|
+
},
|
|
100
115
|
"./field": {
|
|
101
116
|
"types": "./dist/components/field/index.d.ts",
|
|
102
117
|
"import": "./dist/components/field/index.js"
|
|
103
118
|
},
|
|
119
|
+
"./file-input": {
|
|
120
|
+
"types": "./dist/components/file-input/index.d.ts",
|
|
121
|
+
"import": "./dist/components/file-input/index.js"
|
|
122
|
+
},
|
|
104
123
|
"./floating": {
|
|
105
124
|
"types": "./dist/components/floating/index.d.ts",
|
|
106
125
|
"import": "./dist/components/floating/index.js"
|
|
@@ -109,6 +128,10 @@
|
|
|
109
128
|
"types": "./dist/components/focus-trap/index.d.ts",
|
|
110
129
|
"import": "./dist/components/focus-trap/index.js"
|
|
111
130
|
},
|
|
131
|
+
"./hover-card": {
|
|
132
|
+
"types": "./dist/components/hover-card/index.d.ts",
|
|
133
|
+
"import": "./dist/components/hover-card/index.js"
|
|
134
|
+
},
|
|
112
135
|
"./icon-button": {
|
|
113
136
|
"types": "./dist/components/icon-button/index.d.ts",
|
|
114
137
|
"import": "./dist/components/icon-button/index.js"
|
|
@@ -121,6 +144,10 @@
|
|
|
121
144
|
"types": "./dist/components/modal/index.d.ts",
|
|
122
145
|
"import": "./dist/components/modal/index.js"
|
|
123
146
|
},
|
|
147
|
+
"./multi-select": {
|
|
148
|
+
"types": "./dist/components/multi-select/index.d.ts",
|
|
149
|
+
"import": "./dist/components/multi-select/index.js"
|
|
150
|
+
},
|
|
124
151
|
"./number-input": {
|
|
125
152
|
"types": "./dist/components/number-input/index.d.ts",
|
|
126
153
|
"import": "./dist/components/number-input/index.js"
|
|
@@ -149,6 +176,10 @@
|
|
|
149
176
|
"types": "./dist/components/scroll-area/index.d.ts",
|
|
150
177
|
"import": "./dist/components/scroll-area/index.js"
|
|
151
178
|
},
|
|
179
|
+
"./segmented-control": {
|
|
180
|
+
"types": "./dist/components/segmented-control/index.d.ts",
|
|
181
|
+
"import": "./dist/components/segmented-control/index.js"
|
|
182
|
+
},
|
|
152
183
|
"./select": {
|
|
153
184
|
"types": "./dist/components/select/index.d.ts",
|
|
154
185
|
"import": "./dist/components/select/index.js"
|
|
@@ -165,6 +196,10 @@
|
|
|
165
196
|
"types": "./dist/components/tabs/index.d.ts",
|
|
166
197
|
"import": "./dist/components/tabs/index.js"
|
|
167
198
|
},
|
|
199
|
+
"./tags-input": {
|
|
200
|
+
"types": "./dist/components/tags-input/index.d.ts",
|
|
201
|
+
"import": "./dist/components/tags-input/index.js"
|
|
202
|
+
},
|
|
168
203
|
"./teleport-provider": {
|
|
169
204
|
"types": "./dist/components/teleport-provider/index.d.ts",
|
|
170
205
|
"import": "./dist/components/teleport-provider/index.js"
|
|
@@ -177,6 +212,10 @@
|
|
|
177
212
|
"types": "./dist/components/toast/index.d.ts",
|
|
178
213
|
"import": "./dist/components/toast/index.js"
|
|
179
214
|
},
|
|
215
|
+
"./toolbar": {
|
|
216
|
+
"types": "./dist/components/toolbar/index.d.ts",
|
|
217
|
+
"import": "./dist/components/toolbar/index.js"
|
|
218
|
+
},
|
|
180
219
|
"./tooltip": {
|
|
181
220
|
"types": "./dist/components/tooltip/index.d.ts",
|
|
182
221
|
"import": "./dist/components/tooltip/index.js"
|
|
@@ -190,36 +229,6 @@
|
|
|
190
229
|
"./styles-manifest.json": "./src/styles/styles-manifest.json",
|
|
191
230
|
"./scss/*.scss": "./src/styles/*.scss"
|
|
192
231
|
},
|
|
193
|
-
"scripts": {
|
|
194
|
-
"dev": "pnpm run storybook",
|
|
195
|
-
"publication:sync": "node scripts/sync-package-publication.mjs --write",
|
|
196
|
-
"publication:check": "node scripts/sync-package-publication.mjs --check",
|
|
197
|
-
"publication:verify": "node scripts/verify-package-publication.mjs",
|
|
198
|
-
"tokens:build": "style-dictionary build --config scripts/tokens.config.mjs --silent",
|
|
199
|
-
"tokens:check": "node scripts/check-tokens.mjs",
|
|
200
|
-
"typecheck": "vue-tsc -b tsconfig.app.json tsconfig.node.json tsconfig.test.json",
|
|
201
|
-
"typecheck:storybook": "vue-tsc -p tsconfig.storybook.json --noEmit",
|
|
202
|
-
"lint": "oxlint",
|
|
203
|
-
"lint:fix": "oxlint --fix",
|
|
204
|
-
"format": "oxfmt",
|
|
205
|
-
"format:check": "oxfmt --check",
|
|
206
|
-
"test": "vitest run --project=unit --project=tooling",
|
|
207
|
-
"test:consumer-types:built": "tsc -p tests/fixtures/consumer-types/tsconfig.bundler.json && tsc -p tests/fixtures/consumer-types/tsconfig.nodenext.json",
|
|
208
|
-
"test:bundle:built": "node scripts/check-package-bundle.mjs",
|
|
209
|
-
"test:consumer-fixture:built": "node tests/fixtures/consumer-app/check.mjs && vue-tsc -p tests/fixtures/consumer-app/tsconfig.json --noEmit && vite build --config tests/fixtures/consumer-app/vite.config.ts && node tests/fixtures/consumer-app/assertions.mjs",
|
|
210
|
-
"test:package": "pnpm run build && pnpm run publication:verify && pnpm run test:bundle:built && pnpm run test:consumer-types:built && pnpm run test:consumer-fixture:built",
|
|
211
|
-
"test:watch": "vitest --project=unit --project=tooling",
|
|
212
|
-
"test:typecheck": "vitest run --project=unit --project=tooling --typecheck",
|
|
213
|
-
"test:storybook": "vitest run --project=storybook-light --project=storybook-dark",
|
|
214
|
-
"build": "pnpm run publication:check && pnpm run tokens:build && pnpm run tokens:check && pnpm run typecheck && vite build",
|
|
215
|
-
"verify": "pnpm run lint && pnpm run format:check && pnpm run typecheck:storybook && pnpm run test && pnpm run test:storybook && pnpm run test:package",
|
|
216
|
-
"prepublishOnly": "pnpm run verify",
|
|
217
|
-
"preview": "vite preview",
|
|
218
|
-
"storybook": "pnpm run tokens:build && storybook dev -p 6006 --no-open",
|
|
219
|
-
"build-storybook": "pnpm run tokens:build && pnpm run tokens:check && pnpm run typecheck:storybook && storybook build",
|
|
220
|
-
"changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -o CHANGELOG.md",
|
|
221
|
-
"release": "pnpm run verify && bumpp --git-check --all --commit \"chore(release): v%s\" --tag \"v%s\" --execute \"pnpm run changelog\""
|
|
222
|
-
},
|
|
223
232
|
"peerDependencies": {
|
|
224
233
|
"@vue/compiler-vapor": "3.6.0-rc.2",
|
|
225
234
|
"unplugin-icons": "^23.0.1",
|
|
@@ -248,12 +257,7 @@
|
|
|
248
257
|
"@vitest/browser-playwright": "^4.1.10",
|
|
249
258
|
"@vue/compiler-vapor": "3.6.0-rc.2",
|
|
250
259
|
"@vue/tsconfig": "^0.9.1",
|
|
251
|
-
"bumpp": "^12.0.0",
|
|
252
|
-
"conventional-changelog": "^8.1.0",
|
|
253
|
-
"conventional-changelog-conventionalcommits": "^10.2.1",
|
|
254
260
|
"jsdom": "^29.1.1",
|
|
255
|
-
"oxfmt": "^0.60.0",
|
|
256
|
-
"oxlint": "^1.75.0",
|
|
257
261
|
"playwright": "^1.61.1",
|
|
258
262
|
"sass-embedded": "^1.100.0",
|
|
259
263
|
"storybook": "^10.5.3",
|
|
@@ -265,10 +269,34 @@
|
|
|
265
269
|
"vite-plugin-dts": "^5.0.3",
|
|
266
270
|
"vitest": "^4.1.10",
|
|
267
271
|
"vue": "3.6.0-rc.2",
|
|
268
|
-
"vue-tsc": "^3.3.
|
|
272
|
+
"vue-tsc": "^3.3.8"
|
|
269
273
|
},
|
|
270
274
|
"repository": {
|
|
271
275
|
"type": "git",
|
|
272
|
-
"url": "https://github.com/daopk/ropav"
|
|
276
|
+
"url": "https://github.com/daopk/ropav",
|
|
277
|
+
"directory": "packages/ropav"
|
|
278
|
+
},
|
|
279
|
+
"scripts": {
|
|
280
|
+
"dev": "pnpm run storybook",
|
|
281
|
+
"publication:sync": "node scripts/sync-package-publication.mjs --write",
|
|
282
|
+
"publication:check": "node scripts/sync-package-publication.mjs --check",
|
|
283
|
+
"publication:verify": "node scripts/verify-package-publication.mjs",
|
|
284
|
+
"tokens:build": "style-dictionary build --config scripts/tokens.config.mjs --silent",
|
|
285
|
+
"tokens:check": "node scripts/check-tokens.mjs",
|
|
286
|
+
"typecheck": "vue-tsc -b tsconfig.app.json tsconfig.node.json tsconfig.test.json",
|
|
287
|
+
"typecheck:storybook": "vue-tsc -p tsconfig.storybook.json --noEmit",
|
|
288
|
+
"test": "vitest run --project=unit --project=tooling",
|
|
289
|
+
"test:consumer-types:built": "tsc -p tests/fixtures/consumer-types/tsconfig.bundler.json && tsc -p tests/fixtures/consumer-types/tsconfig.nodenext.json",
|
|
290
|
+
"test:bundle:built": "node scripts/check-package-bundle.mjs",
|
|
291
|
+
"test:consumer-fixture:built": "node tests/fixtures/consumer-app/check.mjs && vue-tsc -p tests/fixtures/consumer-app/tsconfig.json --noEmit && vite build --config tests/fixtures/consumer-app/vite.config.ts && node tests/fixtures/consumer-app/assertions.mjs",
|
|
292
|
+
"test:package": "pnpm run build && pnpm run publication:verify && pnpm run test:bundle:built && pnpm run test:consumer-types:built && pnpm run test:consumer-fixture:built",
|
|
293
|
+
"test:watch": "vitest --project=unit --project=tooling",
|
|
294
|
+
"test:typecheck": "vitest run --project=unit --project=tooling --typecheck",
|
|
295
|
+
"test:storybook": "vitest run --project=storybook-light --project=storybook-dark",
|
|
296
|
+
"build": "pnpm run publication:check && pnpm run tokens:check && pnpm run typecheck && vite build",
|
|
297
|
+
"verify": "pnpm run typecheck:storybook && pnpm run test && pnpm run test:storybook && pnpm run test:package",
|
|
298
|
+
"preview": "vite preview",
|
|
299
|
+
"storybook": "pnpm run tokens:check && storybook dev -p 6006 --no-open",
|
|
300
|
+
"build-storybook": "pnpm run tokens:check && pnpm run typecheck:storybook && storybook build"
|
|
273
301
|
}
|
|
274
|
-
}
|
|
302
|
+
}
|
package/src/styles/_mixins.scss
CHANGED
|
@@ -108,6 +108,32 @@ $rp-component-colors:
|
|
|
108
108
|
padding: var(--rp-spacing-1) 0;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
@mixin bordered-floating-arrow {
|
|
112
|
+
background-color: inherit;
|
|
113
|
+
border: inherit;
|
|
114
|
+
rotate: 45deg;
|
|
115
|
+
|
|
116
|
+
&[data-side='top'] {
|
|
117
|
+
border-top-color: transparent;
|
|
118
|
+
border-left-color: transparent;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
&[data-side='right'] {
|
|
122
|
+
border-top-color: transparent;
|
|
123
|
+
border-right-color: transparent;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
&[data-side='bottom'] {
|
|
127
|
+
border-right-color: transparent;
|
|
128
|
+
border-bottom-color: transparent;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
&[data-side='left'] {
|
|
132
|
+
border-bottom-color: transparent;
|
|
133
|
+
border-left-color: transparent;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
111
137
|
@mixin inline-icon($size: 1em) {
|
|
112
138
|
display: inline-flex;
|
|
113
139
|
align-items: center;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export type HoverDisclosureInteractionPart = 'trigger' | 'content';
|
|
2
|
-
export interface HoverDisclosureInteractionState {
|
|
3
|
-
contentFocused: boolean;
|
|
4
|
-
contentHovered: boolean;
|
|
5
|
-
touchClickPending: boolean;
|
|
6
|
-
touchPinned: boolean;
|
|
7
|
-
touchPointerActive: boolean;
|
|
8
|
-
triggerFocused: boolean;
|
|
9
|
-
triggerHovered: boolean;
|
|
10
|
-
}
|
|
11
|
-
export type HoverDisclosureInteractionAction = {
|
|
12
|
-
type: 'hover';
|
|
13
|
-
part: HoverDisclosureInteractionPart;
|
|
14
|
-
active: boolean;
|
|
15
|
-
} | {
|
|
16
|
-
type: 'focus';
|
|
17
|
-
part: HoverDisclosureInteractionPart;
|
|
18
|
-
active: boolean;
|
|
19
|
-
} | {
|
|
20
|
-
type: 'pointer-down';
|
|
21
|
-
touch: boolean;
|
|
22
|
-
} | {
|
|
23
|
-
type: 'pointer-up';
|
|
24
|
-
touch: boolean;
|
|
25
|
-
} | {
|
|
26
|
-
type: 'pointer-cancel';
|
|
27
|
-
} | {
|
|
28
|
-
type: 'consume-touch-click';
|
|
29
|
-
} | {
|
|
30
|
-
type: 'set-touch-pinned';
|
|
31
|
-
pinned: boolean;
|
|
32
|
-
} | {
|
|
33
|
-
type: 'reset';
|
|
34
|
-
part: HoverDisclosureInteractionPart | 'all';
|
|
35
|
-
};
|
|
36
|
-
export interface HoverDisclosureInteractionModel {
|
|
37
|
-
read: () => Readonly<HoverDisclosureInteractionState>;
|
|
38
|
-
send: (action: HoverDisclosureInteractionAction) => Readonly<HoverDisclosureInteractionState>;
|
|
39
|
-
}
|
|
40
|
-
export declare function createHoverDisclosureInteractionModel(): HoverDisclosureInteractionModel;
|
|
41
|
-
export declare function hasActiveHoverDisclosureInteraction(state: Readonly<HoverDisclosureInteractionState>): boolean;
|
|
42
|
-
export declare function reduceHoverDisclosureInteraction(state: Readonly<HoverDisclosureInteractionState>, action: HoverDisclosureInteractionAction): HoverDisclosureInteractionState;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { ComputedRef } from 'vue';
|
|
2
|
-
import { HoverDisclosureInteractionModel, HoverDisclosureInteractionPart } from './hoverDisclosureInteractionModel.js';
|
|
3
|
-
import { HoverDisclosureChangeRequest } from './useHoverDisclosureOpenState.js';
|
|
4
|
-
import { HoverDisclosureTargetState } from './useHoverDisclosureTargetBinding.js';
|
|
5
|
-
import { HoverDisclosureContentProps, HoverDisclosureState, HoverDisclosureTriggerProps, UseHoverDisclosureOptions } from './types.js';
|
|
6
|
-
interface HoverDisclosureInteractionCommands {
|
|
7
|
-
cancelScheduledClose: () => void;
|
|
8
|
-
isDisabled: ComputedRef<boolean>;
|
|
9
|
-
isOpen: ComputedRef<boolean>;
|
|
10
|
-
isRequestedOpen: () => boolean;
|
|
11
|
-
request: (change: HoverDisclosureChangeRequest) => void;
|
|
12
|
-
}
|
|
13
|
-
interface UseHoverDisclosureInteractionsOptions {
|
|
14
|
-
commands: HoverDisclosureInteractionCommands;
|
|
15
|
-
interaction: HoverDisclosureInteractionModel;
|
|
16
|
-
options: Readonly<UseHoverDisclosureOptions>;
|
|
17
|
-
state: ComputedRef<HoverDisclosureState>;
|
|
18
|
-
targets: HoverDisclosureTargetState;
|
|
19
|
-
}
|
|
20
|
-
export declare function useHoverDisclosureInteractions({ commands, interaction, options, state, targets, }: UseHoverDisclosureInteractionsOptions): {
|
|
21
|
-
bindingAdapter: {
|
|
22
|
-
contentListeners: readonly [readonly ["pointerenter", EventListener], readonly ["pointerleave", EventListener], readonly ["pointerdown", EventListener], readonly ["focusin", EventListener], readonly ["focusout", EventListener], readonly ["keydown", EventListener]];
|
|
23
|
-
isOutsideDismissalActive: () => boolean;
|
|
24
|
-
onDocumentKeydown: (event: KeyboardEvent) => void;
|
|
25
|
-
onOutsidePointerdown: (event: PointerEvent) => void;
|
|
26
|
-
onTargetDetached: (part: HoverDisclosureInteractionPart) => void;
|
|
27
|
-
triggerListeners: readonly [readonly ["pointerenter", EventListener], readonly ["pointerleave", EventListener], readonly ["pointerdown", EventListener], readonly ["pointerup", EventListener], readonly ["pointercancel", EventListener], readonly ["click", EventListener], readonly ["focusin", EventListener], readonly ["focusout", EventListener], readonly ["keydown", EventListener]];
|
|
28
|
-
};
|
|
29
|
-
contentProps: ComputedRef<HoverDisclosureContentProps>;
|
|
30
|
-
triggerProps: ComputedRef<HoverDisclosureTriggerProps>;
|
|
31
|
-
};
|
|
32
|
-
export {};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { HoverDisclosureInteractionModel } from './hoverDisclosureInteractionModel.js';
|
|
2
|
-
import { HoverDisclosureOpenChangeReason, HoverDisclosureState, UseHoverDisclosureOptions } from './types.js';
|
|
3
|
-
export interface HoverDisclosureChangeRequest {
|
|
4
|
-
event?: Event;
|
|
5
|
-
open: boolean;
|
|
6
|
-
reason: HoverDisclosureOpenChangeReason;
|
|
7
|
-
timing: 'delayed' | 'immediate';
|
|
8
|
-
}
|
|
9
|
-
interface UseHoverDisclosureOpenStateOptions {
|
|
10
|
-
interaction: HoverDisclosureInteractionModel;
|
|
11
|
-
onContentClosed: () => void;
|
|
12
|
-
options: Readonly<UseHoverDisclosureOptions>;
|
|
13
|
-
}
|
|
14
|
-
export declare function useHoverDisclosureOpenState({ interaction, onContentClosed, options, }: UseHoverDisclosureOpenStateOptions): {
|
|
15
|
-
cancelScheduledClose: () => void;
|
|
16
|
-
close: () => void;
|
|
17
|
-
isDisabled: import('vue').ComputedRef<boolean>;
|
|
18
|
-
isOpen: import('vue').ComputedRef<boolean>;
|
|
19
|
-
isRequestedOpen: () => boolean;
|
|
20
|
-
open: () => void;
|
|
21
|
-
request: (change: HoverDisclosureChangeRequest) => void;
|
|
22
|
-
state: import('vue').ComputedRef<HoverDisclosureState>;
|
|
23
|
-
toggle: () => void;
|
|
24
|
-
};
|
|
25
|
-
export {};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { shallowRef, ComputedRef } from 'vue';
|
|
2
|
-
import { UseHoverDisclosureOptions } from './types.js';
|
|
3
|
-
import { HoverDisclosureInteractionPart } from './hoverDisclosureInteractionModel.js';
|
|
4
|
-
export type HoverDisclosureTargetListener = readonly [type: string, listener: EventListener];
|
|
5
|
-
export interface HoverDisclosureTargetState {
|
|
6
|
-
contentElement: Element | null;
|
|
7
|
-
resolvedContentTarget: ReturnType<typeof shallowRef<Element | null>>;
|
|
8
|
-
resolvedInteractionTarget: ReturnType<typeof shallowRef<Element | null>>;
|
|
9
|
-
triggerElement: Element | null;
|
|
10
|
-
}
|
|
11
|
-
interface HoverDisclosureBindingAdapter {
|
|
12
|
-
contentListeners: readonly HoverDisclosureTargetListener[];
|
|
13
|
-
isOutsideDismissalActive: () => boolean;
|
|
14
|
-
onDocumentKeydown: (event: KeyboardEvent) => void;
|
|
15
|
-
onOutsidePointerdown: (event: PointerEvent) => void;
|
|
16
|
-
onTargetDetached: (part: HoverDisclosureInteractionPart) => void;
|
|
17
|
-
triggerListeners: readonly HoverDisclosureTargetListener[];
|
|
18
|
-
}
|
|
19
|
-
interface UseHoverDisclosureTargetBindingOptions {
|
|
20
|
-
adapter: HoverDisclosureBindingAdapter;
|
|
21
|
-
isOpen: ComputedRef<boolean>;
|
|
22
|
-
options: Readonly<UseHoverDisclosureOptions>;
|
|
23
|
-
targets: HoverDisclosureTargetState;
|
|
24
|
-
}
|
|
25
|
-
export declare function createHoverDisclosureTargetState(): HoverDisclosureTargetState;
|
|
26
|
-
export declare function useHoverDisclosureTargetBinding({ adapter, isOpen, options, targets, }: UseHoverDisclosureTargetBindingOptions): void;
|
|
27
|
-
export {};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Ref, SelectHTMLAttributes } from 'vue';
|
|
2
|
-
import { SelectProps } from './types.js';
|
|
3
|
-
import { SelectValue } from './useSelectNativeValue.js';
|
|
4
|
-
export declare function useSelectNativeControl(props: Readonly<SelectProps>, emitUpdate: (value: SelectValue) => void, triggerRef: Readonly<Ref<HTMLElement | null>>): {
|
|
5
|
-
nativeSelectRef: Ref<HTMLSelectElement | null, HTMLSelectElement | null>;
|
|
6
|
-
selectedValue: import('vue').ComputedRef<SelectValue>;
|
|
7
|
-
nativeInputAttrs: import('vue').ComputedRef<SelectHTMLAttributes>;
|
|
8
|
-
requestValueUpdate: (value: SelectValue) => void;
|
|
9
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { SelectProps } from './types.js';
|
|
2
|
-
export type SelectValue = string | number | null;
|
|
3
|
-
export declare function useSelectNativeValue(props: Readonly<SelectProps>, emitUpdate: (value: SelectValue) => void): {
|
|
4
|
-
nativeSelectRef: import('vue').Ref<HTMLSelectElement | null, HTMLSelectElement | null>;
|
|
5
|
-
controllable: import('../../composables/useControllableValue.js').UseControllableValueReturn<SelectValue>;
|
|
6
|
-
getNativeValue: (select: HTMLSelectElement) => string | number | null;
|
|
7
|
-
syncNativeSelection: (value: SelectValue) => void;
|
|
8
|
-
requestValueUpdate: (value: SelectValue) => void;
|
|
9
|
-
};
|
package/dist/pointer.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region src/utils/dom/pointer.ts
|
|
2
|
-
function getPointerId(event) {
|
|
3
|
-
return Number.isFinite(event.pointerId) ? event.pointerId : void 0;
|
|
4
|
-
}
|
|
5
|
-
function isMatchingPointer(event, pointerId) {
|
|
6
|
-
return pointerId === void 0 || getPointerId(event) === pointerId;
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
|
-
export { isMatchingPointer as n, getPointerId as t };
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# Code architecture
|
|
2
|
-
|
|
3
|
-
This guide defines the source structure expected from contributors. The goal is a predictable
|
|
4
|
-
codebase where UI files describe rendering, behavior is testable through small interfaces, and
|
|
5
|
-
shared logic has one obvious home.
|
|
6
|
-
|
|
7
|
-
## Module seams
|
|
8
|
-
|
|
9
|
-
A module should hide a meaningful amount of behavior behind a small interface. Extract code around
|
|
10
|
-
a responsibility, not merely to reduce a line count. A useful extraction makes callers simpler and
|
|
11
|
-
lets tests exercise the same interface that production code uses.
|
|
12
|
-
|
|
13
|
-
Use this dependency direction:
|
|
14
|
-
|
|
15
|
-
```text
|
|
16
|
-
Vue components and component-local modules
|
|
17
|
-
-> internal composables
|
|
18
|
-
-> public composables
|
|
19
|
-
-> utilities
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
A higher layer may also import a lower layer directly. Lower layers must not import higher layers:
|
|
23
|
-
|
|
24
|
-
- `src/utils/` does not import components or composables.
|
|
25
|
-
- `src/composables/` does not import components or internal modules.
|
|
26
|
-
- `src/internal/` does not import components.
|
|
27
|
-
- Components may compose other components when the dependency remains acyclic.
|
|
28
|
-
|
|
29
|
-
## Where code belongs
|
|
30
|
-
|
|
31
|
-
| Location | Responsibility |
|
|
32
|
-
| ----------------------------------------- | --------------------------------------------------------------------- |
|
|
33
|
-
| `src/components/<name>/*.vue` | Template, bindings, slots, and lightweight view-derived state |
|
|
34
|
-
| `src/components/<name>/useX.ts` | Component-specific reactive state, lifecycle, and event orchestration |
|
|
35
|
-
| `src/components/<name>/<concern>Model.ts` | Pure behavior that encodes only that component's contract |
|
|
36
|
-
| `src/internal/composables/` | Shared reactive behavior that is not part of the package interface |
|
|
37
|
-
| `src/composables/` | Reusable public composables exported by the package |
|
|
38
|
-
| `src/utils/` | Reusable runtime helpers without component state or lifecycle |
|
|
39
|
-
| `src/utils/dom/` | Reusable helpers that operate on browser and DOM primitives |
|
|
40
|
-
| `tests/`, `tooling/`, `scripts/` | Test, build, and repository automation helpers |
|
|
41
|
-
|
|
42
|
-
Do not add catch-all `utils`, `helpers`, or `core` modules beside a component. Keep a pure helper
|
|
43
|
-
local when it expresses one component's contract, and give it a semantic name such as
|
|
44
|
-
`sliderModel`. Move it to `src/utils/` once more than one feature needs the behavior.
|
|
45
|
-
|
|
46
|
-
## Component shape
|
|
47
|
-
|
|
48
|
-
Production SFCs use `<script setup lang="ts" vapor>` and remain zero-VDOM. Do not use `h`, `VNode`,
|
|
49
|
-
`defineComponent`, `createVNode`, or related VDOM block helpers in production source.
|
|
50
|
-
|
|
51
|
-
Keep SFC blocks in this order:
|
|
52
|
-
|
|
53
|
-
1. `<template>`
|
|
54
|
-
2. `<script setup lang="ts" vapor>`
|
|
55
|
-
3. `<style>`
|
|
56
|
-
|
|
57
|
-
Within the script block, use this order:
|
|
58
|
-
|
|
59
|
-
1. Imports
|
|
60
|
-
2. `defineOptions`, props defaults, emits, and slots
|
|
61
|
-
3. Composable state and template refs
|
|
62
|
-
4. View-derived computed attributes
|
|
63
|
-
5. Small event adapters and `defineExpose`
|
|
64
|
-
|
|
65
|
-
A short computed value used only to bind the template can stay in the SFC. Move state transitions,
|
|
66
|
-
timers, document listeners, multi-step event handling, and reusable calculations behind a
|
|
67
|
-
composable or pure model interface.
|
|
68
|
-
|
|
69
|
-
## Function design
|
|
70
|
-
|
|
71
|
-
Oxlint enforces a conservative baseline of cyclomatic complexity 20, nesting depth 4, at most 5
|
|
72
|
-
parameters, and at most 250 non-blank, non-comment lines per function. These are upper bounds, not
|
|
73
|
-
targets.
|
|
74
|
-
|
|
75
|
-
- Give each function one reason to change.
|
|
76
|
-
- Prefer guard clauses over deeply nested branches.
|
|
77
|
-
- Use an options object when several parameters describe one concept.
|
|
78
|
-
- Split orchestration into named steps, while keeping the external interface small.
|
|
79
|
-
- Accept dependencies or callbacks at the module seam instead of constructing hard-to-test global
|
|
80
|
-
dependencies inside the implementation.
|
|
81
|
-
- Return observable results where practical; isolate side effects in lifecycle or event adapters.
|
|
82
|
-
|
|
83
|
-
Do not create shallow pass-through functions solely to satisfy a metric. A refactor should improve
|
|
84
|
-
the caller, the module interface, or the test surface.
|
|
85
|
-
|
|
86
|
-
## Imports and package interfaces
|
|
87
|
-
|
|
88
|
-
- Import utilities directly from their module, for example `@/utils/number`; do not add a utils
|
|
89
|
-
barrel.
|
|
90
|
-
- Component `index.ts` files define package-facing exports. Internal code should not import from the
|
|
91
|
-
root package barrel.
|
|
92
|
-
- Keep imports acyclic. If two modules need each other, move the shared behavior to the lowest
|
|
93
|
-
layer that owns the concept.
|
|
94
|
-
- Use `import type` for type-only dependencies.
|
|
95
|
-
|
|
96
|
-
## Testing
|
|
97
|
-
|
|
98
|
-
Test through the interface of the extracted module:
|
|
99
|
-
|
|
100
|
-
- Pure models and utilities use deterministic unit tests.
|
|
101
|
-
- Composables test returned state and commands, using the smallest host needed for lifecycle
|
|
102
|
-
behavior.
|
|
103
|
-
- Component tests cover DOM integration, events, accessibility, and public rendering contracts.
|
|
104
|
-
- Storybook tests cover visual and interaction scenarios that depend on real browser layout.
|
|
105
|
-
|
|
106
|
-
Tests should assert observable behavior rather than private implementation details. Refactoring a
|
|
107
|
-
module internally should not require rewriting its behavioral tests.
|
|
108
|
-
|
|
109
|
-
## Contributor checklist
|
|
110
|
-
|
|
111
|
-
Before opening a pull request:
|
|
112
|
-
|
|
113
|
-
- The SFC primarily adapts props, slots, and composable results to the template.
|
|
114
|
-
- New reusable helpers live in `src/utils/`; feature-only pure logic has a semantic local name.
|
|
115
|
-
- Dependency direction remains downward and acyclic.
|
|
116
|
-
- Functions stay below the enforced complexity, depth, length, and parameter limits.
|
|
117
|
-
- New behavior is tested at the module interface.
|
|
118
|
-
- `pnpm run verify` passes.
|