@retailcrm/embed-ui-v1-components 0.9.19 → 0.9.22-alpha.1

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.
Files changed (123) hide show
  1. package/AGENTS.md +9 -1
  2. package/README.md +5 -2
  3. package/assets/sprites/actions/add-square-outlined.svg +8 -0
  4. package/assets/sprites/actions/drag.svg +8 -0
  5. package/bin/embed-ui-v1-components.mjs +231 -46
  6. package/bin/postinstall.mjs +3 -2
  7. package/dist/host.cjs +1223 -501
  8. package/dist/host.css +637 -10
  9. package/dist/host.d.ts +152 -78
  10. package/dist/host.js +1224 -502
  11. package/dist/remote.cjs +1358 -298
  12. package/dist/remote.d.ts +805 -67
  13. package/dist/remote.js +1360 -300
  14. package/docs/AI.md +99 -17
  15. package/docs/COMPONENTS.md +58 -59
  16. package/docs/FORMAT.md +10 -10
  17. package/docs/PROFILES.md +39 -22
  18. package/docs/README.md +11 -5
  19. package/docs/profiles/components/UiAddButton.yml +134 -0
  20. package/docs/profiles/components/UiAlert.yml +105 -0
  21. package/docs/profiles/components/UiAvatar.yml +88 -0
  22. package/docs/profiles/{UiAvatarList.yml → components/UiAvatarList.yml} +26 -0
  23. package/docs/profiles/{UiButton.yml → components/UiButton.yml} +14 -8
  24. package/docs/profiles/components/UiCalendar.yml +190 -0
  25. package/docs/profiles/components/UiCheckbox.yml +111 -0
  26. package/docs/profiles/components/UiCollapse.yml +129 -0
  27. package/docs/profiles/components/UiCollapseBox.yml +143 -0
  28. package/docs/profiles/{UiCollapseGroup.yml → components/UiCollapseGroup.yml} +24 -0
  29. package/docs/profiles/components/UiCopyButton.yml +104 -0
  30. package/docs/profiles/components/UiDate.yml +84 -0
  31. package/docs/profiles/components/UiDatePicker.yml +138 -0
  32. package/docs/profiles/components/UiError.yml +123 -0
  33. package/docs/profiles/{UiField.yml → components/UiField.yml} +46 -15
  34. package/docs/profiles/components/UiInfobox.yml +130 -0
  35. package/docs/profiles/components/UiLink.yml +111 -0
  36. package/docs/profiles/components/UiLoader.yml +71 -0
  37. package/docs/profiles/components/UiMenuItem.yml +93 -0
  38. package/docs/profiles/{UiMenuItemGroup.yml → components/UiMenuItemGroup.yml} +25 -0
  39. package/docs/profiles/components/UiModalSidebar.yml +156 -0
  40. package/docs/profiles/components/UiModalWindow.yml +181 -0
  41. package/docs/profiles/{UiModalWindowSurface.yml → components/UiModalWindowSurface.yml} +30 -0
  42. package/docs/profiles/components/UiNumberStepper.yml +100 -0
  43. package/docs/profiles/{UiPageHeader.yml → components/UiPageHeader.yml} +39 -23
  44. package/docs/profiles/components/UiPopconfirm.yml +164 -0
  45. package/docs/profiles/{UiPopper.yml → components/UiPopper.yml} +66 -13
  46. package/docs/profiles/{UiPopperConnector.yml → components/UiPopperConnector.yml} +5 -25
  47. package/docs/profiles/{UiPopperTarget.yml → components/UiPopperTarget.yml} +5 -25
  48. package/docs/profiles/components/UiRadio.yml +91 -0
  49. package/docs/profiles/{UiRadioSwitch.yml → components/UiRadioSwitch.yml} +55 -32
  50. package/docs/profiles/{UiRadioSwitchOption.yml → components/UiRadioSwitchOption.yml} +7 -13
  51. package/docs/profiles/components/UiScrollBox.yml +108 -0
  52. package/docs/profiles/{UiSelect.yml → components/UiSelect.yml} +133 -44
  53. package/docs/profiles/components/UiSelectOption.yml +74 -0
  54. package/docs/profiles/components/UiSelectOptionGroup.yml +66 -0
  55. package/docs/profiles/components/UiSkeleton.yml +82 -0
  56. package/docs/profiles/components/UiSlider.yml +161 -0
  57. package/docs/profiles/components/UiSwitch.yml +123 -0
  58. package/docs/profiles/components/UiTab.yml +234 -0
  59. package/docs/profiles/{UiTabGroup.yml → components/UiTabGroup.yml} +0 -30
  60. package/docs/profiles/components/UiTable.yml +622 -0
  61. package/docs/profiles/{UiTableBodyCell.yml → components/UiTableBodyCell.yml} +26 -0
  62. package/docs/profiles/components/UiTableColumn.yml +87 -0
  63. package/docs/profiles/components/UiTableFooterButton.yml +85 -0
  64. package/docs/profiles/components/UiTableFooterSection.yml +73 -0
  65. package/docs/profiles/{UiTableHeadCell.yml → components/UiTableHeadCell.yml} +26 -0
  66. package/docs/profiles/{UiTableSorter.yml → components/UiTableSorter.yml} +27 -0
  67. package/docs/profiles/components/UiTag.yml +90 -0
  68. package/docs/profiles/{UiTextbox.yml → components/UiTextbox.yml} +20 -32
  69. package/docs/profiles/components/UiTimePicker.yml +144 -0
  70. package/docs/profiles/{UiToggleButton.yml → components/UiToggleButton.yml} +16 -11
  71. package/docs/profiles/{UiToggleGroup.yml → components/UiToggleGroup.yml} +25 -13
  72. package/docs/profiles/{UiToggleGroupOption.yml → components/UiToggleGroupOption.yml} +7 -11
  73. package/docs/profiles/components/UiToolbarButton.yml +87 -0
  74. package/docs/profiles/components/UiToolbarLink.yml +80 -0
  75. package/docs/profiles/components/UiTooltip.yml +97 -0
  76. package/docs/profiles/components/UiTransition.yml +62 -0
  77. package/docs/profiles/components/UiYandexMap.yml +104 -0
  78. package/docs/profiles/pages/CardSettingsPage.yml +58 -0
  79. package/docs/profiles/pages/CollapseBlockPage.yml +46 -0
  80. package/docs/profiles/pages/EntityListPage.yml +66 -0
  81. package/docs/profiles/pages/ModalSidebar.yml +158 -0
  82. package/docs/profiles/pages/ModalWindow.yml +55 -0
  83. package/docs/profiles/pages/MultiColumnPage.yml +27 -0
  84. package/docs/profiles/pages/PageComposition.yml +56 -0
  85. package/package.json +15 -15
  86. package/docs/profiles/UiAddButton.yml +0 -57
  87. package/docs/profiles/UiAlert.yml +0 -48
  88. package/docs/profiles/UiAvatar.yml +0 -48
  89. package/docs/profiles/UiCalendar.yml +0 -48
  90. package/docs/profiles/UiCheckbox.yml +0 -53
  91. package/docs/profiles/UiCollapse.yml +0 -40
  92. package/docs/profiles/UiCollapseBox.yml +0 -51
  93. package/docs/profiles/UiCopyButton.yml +0 -52
  94. package/docs/profiles/UiDate.yml +0 -38
  95. package/docs/profiles/UiDatePicker.yml +0 -59
  96. package/docs/profiles/UiError.yml +0 -32
  97. package/docs/profiles/UiImage.yml +0 -39
  98. package/docs/profiles/UiInfobox.yml +0 -45
  99. package/docs/profiles/UiLink.yml +0 -51
  100. package/docs/profiles/UiLoader.yml +0 -38
  101. package/docs/profiles/UiMenuItem.yml +0 -57
  102. package/docs/profiles/UiModalSidebar.yml +0 -46
  103. package/docs/profiles/UiModalWindow.yml +0 -44
  104. package/docs/profiles/UiNumberStepper.yml +0 -52
  105. package/docs/profiles/UiRadio.yml +0 -38
  106. package/docs/profiles/UiScrollBox.yml +0 -31
  107. package/docs/profiles/UiSelectOption.yml +0 -44
  108. package/docs/profiles/UiSelectOptionGroup.yml +0 -38
  109. package/docs/profiles/UiSkeleton.yml +0 -41
  110. package/docs/profiles/UiSlider.yml +0 -38
  111. package/docs/profiles/UiSwitch.yml +0 -37
  112. package/docs/profiles/UiTab.yml +0 -119
  113. package/docs/profiles/UiTable.yml +0 -152
  114. package/docs/profiles/UiTableColumn.yml +0 -50
  115. package/docs/profiles/UiTableFooterButton.yml +0 -44
  116. package/docs/profiles/UiTableFooterSection.yml +0 -38
  117. package/docs/profiles/UiTag.yml +0 -41
  118. package/docs/profiles/UiTimePicker.yml +0 -46
  119. package/docs/profiles/UiToolbarButton.yml +0 -37
  120. package/docs/profiles/UiToolbarLink.yml +0 -32
  121. package/docs/profiles/UiTooltip.yml +0 -43
  122. package/docs/profiles/UiTransition.yml +0 -27
  123. package/docs/profiles/UiYandexMap.yml +0 -29
@@ -83,31 +83,6 @@ composition:
83
83
  - title: Not always needed
84
84
  notes: Connector-only composition is enough when the trigger already exposes its root element.
85
85
 
86
- examples:
87
- - title: Tooltip anchor
88
- goal: Anchor a floating layer to a specific title or button wrapper.
89
- code: |
90
- <UiPopperConnector>
91
- <UiPopperTarget tag="span">
92
- <span>Title</span>
93
- </UiPopperTarget>
94
-
95
- <UiPopper :visible="open">
96
- Tooltip
97
- </UiPopper>
98
- </UiPopperConnector>
99
- - title: Explicit title-only anchor
100
- goal: Bind the floating layer to a title wrapper instead of the whole row.
101
- code: |
102
- <UiPopperConnector>
103
- <UiPopperTarget tag="span">
104
- <span class="header-title">Title</span>
105
- </UiPopperTarget>
106
-
107
- <UiPopper :visible="open">
108
- Tooltip
109
- </UiPopper>
110
- </UiPopperConnector>
111
86
 
112
87
  ai_notes:
113
88
  do:
@@ -116,3 +91,8 @@ ai_notes:
116
91
  avoid:
117
92
  - Do not treat the wrapper as decorative only; it affects what the floating layer anchors to.
118
93
  - Do not wrap every UiButton or similar trigger with UiPopperTarget if connector already gives the correct anchor.
94
+
95
+ styling:
96
+ notes:
97
+ - Use documented props and slots as the primary styling API.
98
+ - Internal .ui-v1-* classes are descriptive implementation details for reasoning and debugging unless a profile marks them as public theme hooks.
@@ -0,0 +1,91 @@
1
+ component: UiRadio
2
+ summary: >
3
+ UiRadio is the single-choice selection control for exclusive option sets.
4
+ It is the radio-style counterpart to UiCheckbox.
5
+
6
+ public_import:
7
+ from: '@retailcrm/embed-ui-v1-components/remote'
8
+ named:
9
+ - UiRadio
10
+
11
+ examples:
12
+ - title: Example
13
+ code: |
14
+ <template>
15
+ <UiRadio id="delivery-courier" v-model:model="deliveryType" value="courier" name="delivery-type" />
16
+ <label for="delivery-courier">Courier</label>
17
+ </template>
18
+
19
+ <script lang="ts" setup>
20
+ import { ref } from 'vue'
21
+ import { UiRadio } from '@retailcrm/embed-ui-v1-components/remote'
22
+
23
+ const deliveryType = ref('courier')
24
+ </script>
25
+
26
+ use_when:
27
+ - You need one selected value from a fixed set.
28
+
29
+ avoid_when:
30
+ - You need multiple independent selections, use UiCheckbox instead.
31
+
32
+ api:
33
+ key_props:
34
+ - name: model
35
+ - name: value
36
+ - name: required
37
+ - name: disabled
38
+ methods:
39
+ - name: click
40
+ - name: focus
41
+ - name: blur
42
+
43
+ rendered_structure:
44
+ descriptive_only: true
45
+ root:
46
+ shape: span.ui-v1-radio
47
+ tag: span
48
+ notes: One inline wrapper around the visual radio control and label content.
49
+
50
+ geometry:
51
+ layout: inline radio control
52
+ root_display: inline-flex
53
+ width_behavior: content-sized by default
54
+
55
+ behavior:
56
+ notes:
57
+ - Use several UiRadio controls with the same model to represent one exclusive group.
58
+ - The selected value comes from the option value, not from the label text.
59
+
60
+ composition:
61
+ works_well_with:
62
+ - UiField
63
+ - UiRadioSwitch
64
+ patterns:
65
+ - title: Simple exclusive choice
66
+ notes: Use UiRadio for compact vertical or inline lists of mutually exclusive values.
67
+ - title: Rich segmented choice
68
+ notes: Use UiRadioSwitch instead when the options should look like a segmented control or rich section cards.
69
+
70
+ ai_notes:
71
+ do:
72
+ - Use for plain mutually exclusive options.
73
+ - Keep all options in one visible group with clear labels.
74
+ avoid:
75
+ - Do not use for multiple independent selections; use UiCheckbox or UiToggleGroup.
76
+
77
+ accessibility:
78
+ notes:
79
+ - Prefer visible text labels for interactive controls.
80
+ - For icon-only or custom visual content, provide an accessible name through the supported label, title, or ARIA attributes exposed by the component.
81
+ - Preserve native keyboard semantics by using the component root instead of recreating the control with arbitrary markup.
82
+ keyboard:
83
+ - Tab moves focus to the control when it is focusable.
84
+ - Enter or Space activates native button-like controls when the host implementation renders a button.
85
+
86
+ styling:
87
+ notes:
88
+ - Use documented props and slots as the primary styling API.
89
+ - Internal .ui-v1-* classes are descriptive implementation details for reasoning and debugging unless a profile marks them as public theme hooks.
90
+ root_classes:
91
+ - .ui-v1-radio
@@ -16,6 +16,61 @@ related_components:
16
16
  - UiField
17
17
  - UiRadioSwitchOption
18
18
 
19
+ examples:
20
+ - title: Basic switcher
21
+ code: |
22
+ <template>
23
+ <UiRadioSwitch
24
+ v-model:value="mode"
25
+ :options="options"
26
+ />
27
+ </template>
28
+
29
+ <script lang="ts" setup>
30
+ import { ref } from 'vue'
31
+ import { UiRadioSwitch } from '@retailcrm/embed-ui-v1-components/remote'
32
+
33
+ const mode = ref({ key: 'auto' })
34
+
35
+ const options = [
36
+ { label: 'Auto', value: { key: 'auto' } },
37
+ { label: 'Manual', value: { key: 'manual' } },
38
+ ]
39
+ </script>
40
+ - title: Cards with descriptions
41
+ code: |
42
+ <template>
43
+ <UiRadioSwitch
44
+ v-model:value="mode"
45
+ appearance="section"
46
+ rubber
47
+ :equal-fn="equalFn"
48
+ >
49
+ <UiRadioSwitchOption
50
+ label="Auto"
51
+ :value="{ key: 'auto' }"
52
+ description="Automatic mode"
53
+ />
54
+
55
+ <UiRadioSwitchOption
56
+ label="Manual"
57
+ :value="{ key: 'manual' }"
58
+ description="Manual setup"
59
+ />
60
+ </UiRadioSwitch>
61
+ </template>
62
+
63
+ <script lang="ts" setup>
64
+ import { ref } from 'vue'
65
+ import {
66
+ UiRadioSwitch,
67
+ UiRadioSwitchOption,
68
+ } from '@retailcrm/embed-ui-v1-components/remote'
69
+
70
+ const mode = ref({ key: 'auto' })
71
+ const equalFn = (a?: { key: string }, b?: { key: string }) => a?.key === b?.key
72
+ </script>
73
+
19
74
  use_when:
20
75
  - You need one selected value from a small fixed set.
21
76
  - You want a segmented control instead of classic radio circles.
@@ -188,38 +243,6 @@ composition:
188
243
  - title: Section cards
189
244
  notes: Use UiRadioSwitchOption when each choice needs icon, description, or custom checkmark.
190
245
 
191
- examples:
192
- - title: Simple options array
193
- goal: Build a compact single-choice segmented control.
194
- code: |
195
- <UiRadioSwitch
196
- v-model:value="mode"
197
- :options="[
198
- { label: 'Auto', value: 'auto' },
199
- { label: 'Manual', value: 'manual' },
200
- ]"
201
- />
202
- - title: Rich card options
203
- goal: Render section cards with object values and descriptions.
204
- code: |
205
- <UiRadioSwitch
206
- v-model:value="mode"
207
- appearance="section"
208
- rubber
209
- :equal-fn="(a, b) => a?.key === b?.key"
210
- >
211
- <UiRadioSwitchOption
212
- label="Auto"
213
- :value="{ key: 'auto' }"
214
- description="Automatic mode"
215
- />
216
-
217
- <UiRadioSwitchOption
218
- label="Manual"
219
- :value="{ key: 'manual' }"
220
- description="Manual setup"
221
- />
222
- </UiRadioSwitch>
223
246
 
224
247
  ai_notes:
225
248
  do:
@@ -99,19 +99,6 @@ composition:
99
99
  - title: Rich switch option
100
100
  notes: Use when one option needs icon, label, description, and custom selected state.
101
101
 
102
- examples:
103
- - title: Section option
104
- goal: Define one rich option inside a radio switch.
105
- code: |
106
- <UiRadioSwitchOption
107
- label="Manual"
108
- :value="{ key: 'manual' }"
109
- description="Manual setup"
110
- >
111
- <template #icon>
112
- <IconStar />
113
- </template>
114
- </UiRadioSwitchOption>
115
102
 
116
103
  ai_notes:
117
104
  do:
@@ -119,3 +106,10 @@ ai_notes:
119
106
  - Prefer label and description props for simple content and slots for richer custom markup.
120
107
  avoid:
121
108
  - Do not use it as a standalone control outside UiRadioSwitch.
109
+
110
+ styling:
111
+ notes:
112
+ - Use documented props and slots as the primary styling API.
113
+ - Internal .ui-v1-* classes are descriptive implementation details for reasoning and debugging unless a profile marks them as public theme hooks.
114
+ root_classes:
115
+ - .ui-v1-radio-switch-option
@@ -0,0 +1,108 @@
1
+ component: UiScrollBox
2
+ summary: >
3
+ UiScrollBox is a scrollable container for constrained content areas. Use it when content
4
+ should remain inside a dedicated scrolling region instead of growing the whole page.
5
+
6
+ public_import:
7
+ from: '@retailcrm/embed-ui-v1-components/remote'
8
+ named:
9
+ - UiScrollBox
10
+
11
+ examples:
12
+ - title: Example
13
+ code: |
14
+ <template>
15
+ <div :class="$style['wrapper']">
16
+ <UiScrollBox v-bind="$attrs" :class="$style['block']">
17
+ <div :class="[$style['content'], $style['content_tall']]" />
18
+ </UiScrollBox>
19
+
20
+ <UiScrollBox v-bind="$attrs" :class="$style['block']">
21
+ <div :class="[$style['content'], $style['content_wide']]" />
22
+ </UiScrollBox>
23
+ </div>
24
+ </template>
25
+
26
+ <script lang="ts" setup>
27
+ import { UiScrollBox } from '@retailcrm/embed-ui-v1-components/remote'
28
+ </script>
29
+
30
+ <style lang="less" module>
31
+
32
+ .wrapper {
33
+ display: flex;
34
+ }
35
+
36
+ .block {
37
+ width: 120px;
38
+ height: 147px;
39
+ border: 1px solid rgba(30, 34, 72, 0.16);
40
+ border-radius: 8px;
41
+
42
+ &:not(:last-child) {
43
+ margin-right: 8px;
44
+ }
45
+ }
46
+
47
+ .content {
48
+ width: 100%;
49
+ height: 100%;
50
+
51
+ &_wide { width: 300px; }
52
+ &_tall { height: 300px; }
53
+ }
54
+ </style>
55
+
56
+ use_when:
57
+ - You need a bounded scroll area.
58
+ - You need long content inside a fixed-height or fixed-width region.
59
+
60
+ avoid_when:
61
+ - You need normal page scrolling.
62
+
63
+ api:
64
+ key_props: []
65
+
66
+ rendered_structure:
67
+ descriptive_only: true
68
+ root:
69
+ shape: configurable wrapper tag or PerfectScrollbar root
70
+ tag: configurable, div by default
71
+ notes: The root depends on native mode and tag prop, but behaves as a scroll container rather than a visual primitive.
72
+
73
+ geometry:
74
+ layout: scroll container
75
+ root_display: block
76
+ width_behavior: stretches to the size of its layout context
77
+
78
+ behavior:
79
+ notes:
80
+ - Use only when a bounded region should scroll independently.
81
+ - The parent layout must provide meaningful height or width constraints.
82
+
83
+ composition:
84
+ works_well_with:
85
+ - UiModalWindow
86
+ - UiModalSidebar
87
+ - UiTable
88
+ patterns:
89
+ - title: Modal body scrolling
90
+ notes: Use when modal content is long but header and footer should remain accessible.
91
+ - title: Constrained list
92
+ notes: Use for long menu or panel content when full page scrolling is undesirable.
93
+
94
+ ai_notes:
95
+ do:
96
+ - Give the surrounding layout a stable height before relying on scrolling.
97
+ avoid:
98
+ - Do not wrap normal page content in a scroll container by default.
99
+
100
+ accessibility:
101
+ notes:
102
+ - Keep visible labels and slot content meaningful.
103
+ - Prefer documented props and slots over custom DOM replacements so host-side accessibility behavior is preserved.
104
+
105
+ styling:
106
+ notes:
107
+ - Use documented props and slots as the primary styling API.
108
+ - Internal .ui-v1-* classes are descriptive implementation details for reasoning and debugging unless a profile marks them as public theme hooks.
@@ -18,6 +18,139 @@ related_components:
18
18
  - UiPopperConnector
19
19
  - UiPopperTarget
20
20
 
21
+ examples:
22
+ - title: Basic selection
23
+ code: |
24
+ <template>
25
+ <UiSelect placeholder="Assignee">
26
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
27
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
28
+ <UiSelectOption value="philip" label="Philip Williamson" />
29
+ </UiSelect>
30
+ </template>
31
+
32
+ <script lang="ts" setup>
33
+ import {
34
+ UiSelect,
35
+ UiSelectOption,
36
+ } from '@retailcrm/embed-ui-v1-components/remote'
37
+ </script>
38
+ - title: Multiple selection with clearing
39
+ code: |
40
+ <template>
41
+ <UiSelect
42
+ v-model:value="value"
43
+ multiple
44
+ clearable
45
+ placeholder="Assignees"
46
+ >
47
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
48
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
49
+ <UiSelectOption value="philip" label="Philip Williamson" />
50
+ </UiSelect>
51
+ </template>
52
+
53
+ <script lang="ts" setup>
54
+ import { ref } from 'vue'
55
+ import { UiSelect, UiSelectOption } from '@retailcrm/embed-ui-v1-components/remote'
56
+
57
+ const value = ref<string[]>([])
58
+ </script>
59
+ - title: Option search
60
+ code: |
61
+ <template>
62
+ <UiSelect filterable placeholder="Find a user">
63
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
64
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
65
+ <UiSelectOption value="philip" label="Philip Williamson" />
66
+ </UiSelect>
67
+ </template>
68
+
69
+ <script lang="ts" setup>
70
+ import { UiSelect, UiSelectOption } from '@retailcrm/embed-ui-v1-components/remote'
71
+ </script>
72
+ - title: Error state (`invalid`)
73
+ code: |
74
+ <template>
75
+ <UiSelect
76
+ v-model:value="value"
77
+ invalid
78
+ placeholder="User"
79
+ >
80
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
81
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
82
+ </UiSelect>
83
+ </template>
84
+
85
+ <script lang="ts" setup>
86
+ import { ref } from 'vue'
87
+ import { UiSelect, UiSelectOption } from '@retailcrm/embed-ui-v1-components/remote'
88
+
89
+ const value = ref('eduardo')
90
+ </script>
91
+ - title: "`readonly` mode"
92
+ code: |
93
+ <template>
94
+ <UiSelect readonly placeholder="User">
95
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
96
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
97
+ </UiSelect>
98
+ </template>
99
+
100
+ <script lang="ts" setup>
101
+ import { UiSelect, UiSelectOption } from '@retailcrm/embed-ui-v1-components/remote'
102
+ </script>
103
+ - title: "`disabled` mode"
104
+ code: |
105
+ <template>
106
+ <UiSelect disabled placeholder="User">
107
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
108
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
109
+ </UiSelect>
110
+ </template>
111
+
112
+ <script lang="ts" setup>
113
+ import { UiSelect, UiSelectOption } from '@retailcrm/embed-ui-v1-components/remote'
114
+ </script>
115
+ - title: Object options
116
+ code: |
117
+ <template>
118
+ <UiSelect
119
+ :value="{ id: 2, name: 'Eduardo Henry' }"
120
+ :equals-fn="(a, b) => a?.id === b?.id"
121
+ placeholder="User"
122
+ >
123
+ <UiSelectOption :value="{ id: 1, name: 'Kyle Simmons' }" label="Kyle Simmons" />
124
+ <UiSelectOption :value="{ id: 2, name: 'Eduardo Henry' }" label="Eduardo Henry" />
125
+ </UiSelect>
126
+ </template>
127
+
128
+ <script lang="ts" setup>
129
+ import { UiSelect, UiSelectOption } from '@retailcrm/embed-ui-v1-components/remote'
130
+ </script>
131
+ - title: Grouped options
132
+ code: |
133
+ <template>
134
+ <UiSelect placeholder="Employee">
135
+ <UiSelectOptionGroup label="Sales department">
136
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
137
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
138
+ </UiSelectOptionGroup>
139
+
140
+ <UiSelectOptionGroup label="Support">
141
+ <UiSelectOption value="philip" label="Philip Williamson" />
142
+ </UiSelectOptionGroup>
143
+ </UiSelect>
144
+ </template>
145
+
146
+ <script lang="ts" setup>
147
+ import {
148
+ UiSelect,
149
+ UiSelectOption,
150
+ UiSelectOptionGroup,
151
+ } from '@retailcrm/embed-ui-v1-components/remote'
152
+ </script>
153
+
21
154
  use_when:
22
155
  - You need to choose one value from a list.
23
156
  - You need multi-select behavior.
@@ -271,50 +404,6 @@ composition:
271
404
  - title: Popper mental model
272
405
  notes: Think of UiSelect as target plus floating dropdown, not as a single inline control.
273
406
 
274
- examples:
275
- - title: Standard select in a field
276
- goal: Build a labeled select with field semantics.
277
- code: |
278
- <UiField id="assignee" label="Assignee">
279
- <template #default="field">
280
- <UiSelect
281
- :id="field.id"
282
- :invalid="field.invalid"
283
- :placeholder="'Select assignee'"
284
- v-model:value="assignee"
285
- >
286
- <UiSelectOption value="kyle" label="Kyle Simmons" />
287
- <UiSelectOption value="eduardo" label="Eduardo Henry" />
288
- </UiSelect>
289
- </template>
290
- </UiField>
291
- - title: Grouped options
292
- goal: Build a grouped option tree through the safe child components.
293
- code: |
294
- <UiSelect placeholder="Employee">
295
- <UiSelectOptionGroup label="Sales">
296
- <UiSelectOption value="kyle" label="Kyle Simmons" />
297
- </UiSelectOptionGroup>
298
-
299
- <UiSelectOptionGroup label="Support">
300
- <UiSelectOption value="philip" label="Philip Williamson" />
301
- </UiSelectOptionGroup>
302
- </UiSelect>
303
- - title: Object values with equalsFn
304
- goal: Avoid object comparison by reference.
305
- code: |
306
- <UiSelect
307
- v-model:value="selectedUser"
308
- :equals-fn="(left, right) => left?.id === right?.id"
309
- placeholder="Employee"
310
- >
311
- <UiSelectOption
312
- v-for="user in users"
313
- :key="user.id"
314
- :value="user"
315
- :label="user.name"
316
- />
317
- </UiSelect>
318
407
 
319
408
  ai_notes:
320
409
  do:
@@ -0,0 +1,74 @@
1
+ component: UiSelectOption
2
+ summary: >
3
+ UiSelectOption is the base selectable child of UiSelect. It represents one option node
4
+ in the select option tree.
5
+
6
+ public_import:
7
+ from: '@retailcrm/embed-ui-v1-components/remote'
8
+ named:
9
+ - UiSelectOption
10
+
11
+ related_components:
12
+ - UiSelect
13
+ - UiSelectOptionGroup
14
+
15
+ use_when:
16
+ - You need one option inside UiSelect.
17
+
18
+ avoid_when:
19
+ - You need free layout content inside a select dropdown.
20
+
21
+ api:
22
+ key_props:
23
+ - name: value
24
+ - name: label
25
+ - name: description
26
+ - name: disabled
27
+ - name: counter
28
+ - name: accent
29
+
30
+ rendered_structure:
31
+ descriptive_only: true
32
+ root:
33
+ shape: div.ui-v1-select-option
34
+ tag: div
35
+ notes: Renders one option wrapper that usually contains a UiMenuItem row.
36
+
37
+ geometry:
38
+ layout: listbox option row
39
+ root_display: block
40
+ width_behavior: stretches to available dropdown width
41
+
42
+ ai_notes:
43
+ do:
44
+ - Use as the default child node of UiSelect.
45
+ - Provide stable value and human-readable label.
46
+ - Use description for secondary explanation, not for long help text.
47
+ avoid:
48
+ - Do not put arbitrary controls inside options.
49
+
50
+ behavior:
51
+ notes:
52
+ - disabled prevents selection while keeping the option visible.
53
+ - counter and accent help scan dense option lists.
54
+ - In filterable selects, label and description participate in matching.
55
+
56
+ composition:
57
+ works_well_with:
58
+ - UiSelect
59
+ - UiSelectOptionGroup
60
+ patterns:
61
+ - title: Status filter option
62
+ notes: Use concise labels that match the visible table status names.
63
+
64
+ accessibility:
65
+ notes:
66
+ - This component is normally used inside its parent composition; accessibility behavior is completed by the parent component.
67
+ - Keep labels and visible text meaningful because parent keyboard and screen-reader behavior depends on child content.
68
+
69
+ styling:
70
+ notes:
71
+ - Use documented props and slots as the primary styling API.
72
+ - Internal .ui-v1-* classes are descriptive implementation details for reasoning and debugging unless a profile marks them as public theme hooks.
73
+ root_classes:
74
+ - .ui-v1-select-option
@@ -0,0 +1,66 @@
1
+ component: UiSelectOptionGroup
2
+ summary: >
3
+ UiSelectOptionGroup groups related UiSelectOption nodes under a shared label.
4
+
5
+ public_import:
6
+ from: '@retailcrm/embed-ui-v1-components/remote'
7
+ named:
8
+ - UiSelectOptionGroup
9
+
10
+ related_components:
11
+ - UiSelect
12
+ - UiSelectOption
13
+
14
+ use_when:
15
+ - You need grouped select options.
16
+
17
+ avoid_when:
18
+ - You only have a flat list of options.
19
+
20
+ api:
21
+ key_props:
22
+ - name: label
23
+
24
+ rendered_structure:
25
+ descriptive_only: true
26
+ root:
27
+ shape: div.ui-v1-select-option-group
28
+ tag: div
29
+ notes: Renders one structural group wrapper around a heading area and nested option content.
30
+
31
+ geometry:
32
+ layout: block-like option group wrapper
33
+ root_display: block
34
+ width_behavior: stretches to available dropdown width
35
+
36
+ ai_notes:
37
+ do:
38
+ - Use to structure large option lists inside UiSelect.
39
+ - Keep group labels short and categorical.
40
+ avoid:
41
+ - Do not use groups for two or three obvious flat options.
42
+
43
+ behavior:
44
+ notes:
45
+ - Group visibility can change when the parent select is filterable.
46
+ - The group itself is not selectable; child UiSelectOption nodes provide selection.
47
+
48
+ composition:
49
+ works_well_with:
50
+ - UiSelect
51
+ - UiSelectOption
52
+ patterns:
53
+ - title: Large grouped select
54
+ notes: Use for managers by team, statuses by category, or locations by region.
55
+
56
+ accessibility:
57
+ notes:
58
+ - This component is normally used inside its parent composition; accessibility behavior is completed by the parent component.
59
+ - Keep labels and visible text meaningful because parent keyboard and screen-reader behavior depends on child content.
60
+
61
+ styling:
62
+ notes:
63
+ - Use documented props and slots as the primary styling API.
64
+ - Internal .ui-v1-* classes are descriptive implementation details for reasoning and debugging unless a profile marks them as public theme hooks.
65
+ root_classes:
66
+ - .ui-v1-select-option-group