@zap-wunschlachen/wl-shared-components 1.0.76 → 1.0.78

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 (227) hide show
  1. package/.github/workflows/playwright.yml +229 -229
  2. package/.github/workflows/static.yml +61 -61
  3. package/.github/workflows/update-snapshots.yml +37 -37
  4. package/.prettierrc.json +8 -8
  5. package/.storybook/main.ts +18 -18
  6. package/.storybook/preview.ts +37 -37
  7. package/.storybook/storyWrapper.vue +18 -18
  8. package/.storybook/withVuetifyTheme.decorator.ts +21 -21
  9. package/App.vue +139 -139
  10. package/README.md +56 -56
  11. package/docs/assets.md +62 -62
  12. package/heroicons.ts +75 -75
  13. package/index.html +19 -19
  14. package/package.json +71 -71
  15. package/playwright.config.ts +48 -48
  16. package/public/background.svg +60 -60
  17. package/public/style.css +187 -187
  18. package/public/technologies.svg +22 -22
  19. package/scripts/check-translations.ts +352 -352
  20. package/src/assets/css/base.css +242 -242
  21. package/src/assets/css/variables.css +176 -176
  22. package/src/components/Accordion/Accordion.css +65 -65
  23. package/src/components/Accordion/AccordionGroup.vue +88 -88
  24. package/src/components/Accordion/AccordionItem.vue +272 -272
  25. package/src/components/Accordion/presets/default.css +4 -4
  26. package/src/components/Accordion/presets/elevated.css +25 -25
  27. package/src/components/Accordion/presets/filled.css +26 -26
  28. package/src/components/Accordion/presets/index.css +5 -5
  29. package/src/components/Accordion/presets/plain.css +34 -34
  30. package/src/components/Appointment/Card/Actions.css +54 -54
  31. package/src/components/Appointment/Card/Actions.vue +99 -99
  32. package/src/components/Appointment/Card/AnamneseNotification.css +20 -20
  33. package/src/components/Appointment/Card/AnamneseNotification.vue +23 -23
  34. package/src/components/Appointment/Card/Card.css +99 -99
  35. package/src/components/Appointment/Card/Card.vue +97 -97
  36. package/src/components/Appointment/Card/Details.css +62 -62
  37. package/src/components/Appointment/Card/Details.vue +44 -44
  38. package/src/components/Audio/Audio.vue +187 -187
  39. package/src/components/Audio/Waveform.vue +118 -118
  40. package/src/components/Banner/Banner.css +29 -29
  41. package/src/components/Banner/Banner.vue +89 -89
  42. package/src/components/Button/Button.vue +257 -257
  43. package/src/components/CheckBox/CheckBox.css +234 -234
  44. package/src/components/CheckBox/Checkbox.vue +184 -184
  45. package/src/components/DateInput/DateInput.css +2 -2
  46. package/src/components/DateInput/DateInput.vue +376 -370
  47. package/src/components/Dialog/Dialog.css +6 -6
  48. package/src/components/Dialog/Dialog.vue +46 -46
  49. package/src/components/EditField/EditField.css +19 -19
  50. package/src/components/EditField/EditField.vue +211 -211
  51. package/src/components/ErrorPage/ErrorPage.css +172 -172
  52. package/src/components/IconBullet/IconBullet.vue +104 -104
  53. package/src/components/IconBullet/IconBulletList.vue +55 -55
  54. package/src/components/Icons/AdvanceAppointments.vue +161 -161
  55. package/src/components/Icons/Audio/CloudFailed.vue +27 -27
  56. package/src/components/Icons/Audio/CloudSaved.vue +28 -28
  57. package/src/components/Icons/Audio/Delete.vue +22 -22
  58. package/src/components/Icons/Audio/Pause.vue +25 -25
  59. package/src/components/Icons/Audio/Play.vue +22 -22
  60. package/src/components/Icons/Calendar.vue +28 -28
  61. package/src/components/Icons/CalendarNotification.vue +137 -137
  62. package/src/components/Icons/Chair.vue +43 -43
  63. package/src/components/Icons/ChairNotification.vue +46 -46
  64. package/src/components/Icons/Circle.vue +66 -66
  65. package/src/components/Icons/FavIcon.vue +69 -69
  66. package/src/components/Icons/FilledCircle.vue +11 -11
  67. package/src/components/Icons/Group3.vue +57 -57
  68. package/src/components/Icons/Play.vue +16 -16
  69. package/src/components/Icons/RingNotification.vue +65 -65
  70. package/src/components/Icons/SolidArrowRight.vue +14 -14
  71. package/src/components/Icons/checkbox.vue +19 -19
  72. package/src/components/Icons/outlineChecked.vue +38 -38
  73. package/src/components/Input/Input.css +234 -234
  74. package/src/components/Input/Input.vue +281 -281
  75. package/src/components/Laboratory/AppointmentCard/AppointmentCard.css +7 -7
  76. package/src/components/Laboratory/AppointmentCard/AppointmentCard.vue +116 -116
  77. package/src/components/Laboratory/ChatBoxImage/ChatBoxImage.vue +81 -81
  78. package/src/components/Laboratory/ChatMessage/ChatMessage.vue +113 -113
  79. package/src/components/Laboratory/ChatMessage/ChatMessageBadge.css +4 -4
  80. package/src/components/Laboratory/ChatMessage/ChatMessageBadge.vue +99 -99
  81. package/src/components/Laboratory/ChatNotification/ChatNotification.vue +130 -130
  82. package/src/components/Laboratory/DocumentCard/DocumentCard.css +3 -3
  83. package/src/components/Laboratory/DocumentCard/DocumentCard.vue +50 -50
  84. package/src/components/Laboratory/DocumentCard/DocumentCardItem.vue +53 -53
  85. package/src/components/Laboratory/InfoCard/InfoCard.vue +162 -162
  86. package/src/components/Laboratory/MainColumnsBar/MainColumnsBar.vue +102 -102
  87. package/src/components/Laboratory/ProgressCircle/ProgressCircle.vue +152 -152
  88. package/src/components/Laboratory/ProgressLinear/ProgressLinear.css +33 -33
  89. package/src/components/Laboratory/ProgressLinear/ProgressLinear.vue +75 -75
  90. package/src/components/Laboratory/SelectionColumnBar/SelectionColumnBar.vue +92 -92
  91. package/src/components/Laboratory/StatusNotification/StatusNotification.vue +49 -49
  92. package/src/components/Laboratory/TagLabel/TagLabel.vue +126 -126
  93. package/src/components/Laboratory/TagLabelGroup/TagLabelGroup.vue +97 -97
  94. package/src/components/Laboratory/TicketCard/TicketCard.css +3 -3
  95. package/src/components/Laboratory/TicketCard/TicketCard.vue +143 -143
  96. package/src/components/Laboratory/TimeLine/TimeLineEvent.css +18 -18
  97. package/src/components/Laboratory/TimeLine/TimeLineEvent.vue +119 -119
  98. package/src/components/Laboratory/TimeLine/Timeline.css +4 -4
  99. package/src/components/Laboratory/TimeLine/Timeline.vue +30 -30
  100. package/src/components/Loader/Loader.css +78 -78
  101. package/src/components/MaintenanceBanner/MaintenanceBanner.css +353 -353
  102. package/src/components/MaintenanceBanner/MaintenanceBanner.vue +140 -140
  103. package/src/components/MaintenanceBanner/MaintenanceIllustration.vue +54 -54
  104. package/src/components/Modal/Modal.css +5 -5
  105. package/src/components/Modal/Modal.vue +29 -29
  106. package/src/components/NotificationBubble/NotificationBubble.css +4 -4
  107. package/src/components/NotificationBubble/NotificationBubble.vue +90 -90
  108. package/src/components/OtpInput/OtpInput.css +43 -43
  109. package/src/components/OtpInput/OtpInput.vue +181 -181
  110. package/src/components/PhoneInput/PhoneInput.css +151 -126
  111. package/src/components/PhoneInput/PhoneInput.vue +230 -139
  112. package/src/components/RadioGroup/RadioGroup.css +65 -0
  113. package/src/components/RadioGroup/RadioGroup.vue +134 -0
  114. package/src/components/Select/Select.css +172 -172
  115. package/src/components/Select/Select.vue +377 -377
  116. package/src/components/SelectAutocomplete/SelectAutocomplete.css +172 -172
  117. package/src/components/SelectAutocomplete/SelectAutocomplete.vue +414 -414
  118. package/src/components/TextArea/TextArea.css +269 -269
  119. package/src/components/TextArea/TextArea.vue +207 -207
  120. package/src/components/TickBox/TickBox.css +116 -116
  121. package/src/components/TickBox/TickBox.vue +172 -172
  122. package/src/components/Tile/Tile.css +106 -106
  123. package/src/components/Tile/Tile.vue +173 -173
  124. package/src/components/accessibility.css +218 -218
  125. package/src/components/index.ts +110 -109
  126. package/src/constants/iconEnums.ts +3 -3
  127. package/src/i18n/i18n.ts +15 -15
  128. package/src/i18n/locales/de.json +30 -30
  129. package/src/i18n/locales/en.json +30 -30
  130. package/src/index.ts +43 -43
  131. package/src/main.ts +11 -11
  132. package/src/pages/AccordionGroupPage.vue +873 -873
  133. package/src/pages/AllPage.vue +2483 -2365
  134. package/src/pages/SelectPage.vue +1302 -1302
  135. package/src/pages/TilePage.vue +902 -902
  136. package/src/plugins/vuetify.ts +54 -54
  137. package/src/shims-vue.d.ts +30 -30
  138. package/src/utils/index.ts +733 -733
  139. package/src/vite-env.d.ts +1 -1
  140. package/tests/unit/accessibility/component-a11y.spec.ts +657 -657
  141. package/tests/unit/components/Accordion/AccordionGroup.spec.ts +228 -228
  142. package/tests/unit/components/Accordion/AccordionItem.spec.ts +257 -257
  143. package/tests/unit/components/Appointment/AnamneseNotification.spec.ts +176 -176
  144. package/tests/unit/components/Appointment/Card/Actions.spec.ts +436 -436
  145. package/tests/unit/components/Appointment/Card/Card.spec.ts +531 -531
  146. package/tests/unit/components/Appointment/Card/Details.spec.ts +395 -395
  147. package/tests/unit/components/Audio/Audio.spec.ts +403 -403
  148. package/tests/unit/components/Audio/Waveform.spec.ts +483 -483
  149. package/tests/unit/components/Background/Background.spec.ts +177 -177
  150. package/tests/unit/components/Core/AnamneseAnswerDialog.spec.ts +344 -0
  151. package/tests/unit/components/Core/Banner.spec.ts +187 -0
  152. package/tests/unit/components/Core/Button.spec.ts +346 -346
  153. package/tests/unit/components/Core/Checkbox.spec.ts +544 -544
  154. package/tests/unit/components/Core/DateInput.spec.ts +702 -702
  155. package/tests/unit/components/Core/Dialog.spec.ts +448 -448
  156. package/tests/unit/components/Core/EditField.spec.ts +541 -541
  157. package/tests/unit/components/Core/Input.spec.ts +512 -512
  158. package/tests/unit/components/Core/List.spec.ts +163 -0
  159. package/tests/unit/components/Core/ListItem.spec.ts +205 -0
  160. package/tests/unit/components/Core/Modal.spec.ts +518 -518
  161. package/tests/unit/components/Core/NotificationBubble.spec.ts +606 -606
  162. package/tests/unit/components/Core/OtpInput.spec.ts +708 -708
  163. package/tests/unit/components/Core/PhoneInput.spec.ts +757 -619
  164. package/tests/unit/components/Core/RadioGroup.spec.ts +318 -0
  165. package/tests/unit/components/Core/Select.spec.ts +712 -712
  166. package/tests/unit/components/Core/SelectAutocomplete.spec.ts +361 -0
  167. package/tests/unit/components/Core/TextArea.spec.ts +565 -565
  168. package/tests/unit/components/Core/TickBox.spec.ts +836 -836
  169. package/tests/unit/components/Core/Tile.spec.ts +286 -0
  170. package/tests/unit/components/DateInput/DateInput.spec.ts +128 -0
  171. package/tests/unit/components/ErrorPage/ErrorPage.spec.ts +313 -313
  172. package/tests/unit/components/ErrorPage/ErrorPageLogo.spec.ts +153 -153
  173. package/tests/unit/components/IconBullet/IconBullet.spec.ts +356 -356
  174. package/tests/unit/components/IconBullet/IconBulletList.spec.ts +371 -371
  175. package/tests/unit/components/Icons/AdvanceAppointments.spec.ts +186 -186
  176. package/tests/unit/components/Icons/Audio/CloudFailed.spec.ts +108 -108
  177. package/tests/unit/components/Icons/Audio/CloudSaved.spec.ts +149 -149
  178. package/tests/unit/components/Icons/Audio/Delete.spec.ts +158 -158
  179. package/tests/unit/components/Icons/Audio/Pause.spec.ts +208 -208
  180. package/tests/unit/components/Icons/Audio/Play.spec.ts +217 -217
  181. package/tests/unit/components/Icons/CalendarNotification.spec.ts +193 -193
  182. package/tests/unit/components/Icons/Chair.spec.ts +241 -241
  183. package/tests/unit/components/Icons/ChairNotification.spec.ts +318 -318
  184. package/tests/unit/components/Icons/Circle.spec.ts +255 -255
  185. package/tests/unit/components/Icons/FavIcon.spec.ts +259 -259
  186. package/tests/unit/components/Icons/FilledCircle.spec.ts +274 -274
  187. package/tests/unit/components/Icons/Group3.spec.ts +362 -362
  188. package/tests/unit/components/Icons/Logo.spec.ts +229 -229
  189. package/tests/unit/components/Icons/MiniLogo.spec.ts +38 -38
  190. package/tests/unit/components/Icons/RingNotification.spec.ts +400 -400
  191. package/tests/unit/components/Icons/SolidArrowRight.spec.ts +49 -49
  192. package/tests/unit/components/Icons/calendar.spec.ts +293 -293
  193. package/tests/unit/components/Icons/checkbox.spec.ts +315 -315
  194. package/tests/unit/components/Icons/outlineChecked.spec.ts +441 -441
  195. package/tests/unit/components/Icons/play.spec.ts +315 -315
  196. package/tests/unit/components/Laboratory/AppointmentCard.spec.ts +167 -167
  197. package/tests/unit/components/Laboratory/ChatBoxImage.spec.ts +179 -179
  198. package/tests/unit/components/Laboratory/ChatMessage.spec.ts +263 -263
  199. package/tests/unit/components/Laboratory/ChatMessageBadge.spec.ts +282 -282
  200. package/tests/unit/components/Laboratory/ChatNotification.spec.ts +256 -256
  201. package/tests/unit/components/Laboratory/DocumentCard.spec.ts +228 -228
  202. package/tests/unit/components/Laboratory/DocumentCardItem.spec.ts +236 -236
  203. package/tests/unit/components/Laboratory/InfoCard.spec.ts +308 -308
  204. package/tests/unit/components/Laboratory/MainColumnsBar.spec.ts +251 -251
  205. package/tests/unit/components/Laboratory/ProgressCircle.spec.ts +290 -290
  206. package/tests/unit/components/Laboratory/ProgressLinear.spec.ts +275 -275
  207. package/tests/unit/components/Laboratory/SelectionColumnBar.spec.ts +288 -288
  208. package/tests/unit/components/Laboratory/StatusNotification.spec.ts +296 -296
  209. package/tests/unit/components/Laboratory/TagLabel.spec.ts +353 -353
  210. package/tests/unit/components/Laboratory/TagLabelGroup.spec.ts +377 -377
  211. package/tests/unit/components/Laboratory/TicketCard.spec.ts +351 -351
  212. package/tests/unit/components/Laboratory/TimeLineEvent.spec.ts +381 -381
  213. package/tests/unit/components/Laboratory/Timeline.spec.ts +419 -419
  214. package/tests/unit/components/Loader/Loader.spec.ts +197 -197
  215. package/tests/unit/components/MaintenanceBanner/MaintenanceBanner.spec.ts +302 -302
  216. package/tests/unit/constants/iconEnums.spec.ts +39 -39
  217. package/tests/unit/i18n/i18n.spec.ts +88 -88
  218. package/tests/unit/plugins/vuetify.spec.ts +182 -182
  219. package/tests/unit/setup.ts +237 -237
  220. package/tests/unit/src/components/index.spec.ts.skip +192 -192
  221. package/tests/unit/src/index.spec.ts.skip +182 -182
  222. package/tests/unit/src/main.spec.ts +111 -111
  223. package/tests/unit/utils/accessibility.spec.ts +318 -318
  224. package/tests/unit/utils/anamnese.spec.ts +531 -0
  225. package/tsconfig.json +26 -26
  226. package/vite.config.ts +29 -29
  227. package/vitest.config.ts +91 -91
@@ -1,1302 +1,1302 @@
1
- <template>
2
- <div class="page">
3
- <div class="element-container">
4
- <div class="controls">
5
- <h2>Testing Domain: {{ currentDomain }}</h2>
6
- <div class="button-group">
7
- <button
8
- @click="switchToDental"
9
- class="control-btn"
10
- >
11
- Switch to Wunschlachen (Dental)
12
- </button>
13
- <button
14
- @click="switchToCocoon"
15
- class="control-btn"
16
- >
17
- Switch to White Cocoon
18
- </button>
19
- <button
20
- @click="resetDomain"
21
- class="control-btn reset"
22
- >
23
- Reset to Auto-Detect
24
- </button>
25
- </div>
26
- </div>
27
-
28
- <!-- Basic Select Examples -->
29
- <div class="section">
30
- <h3 class="section-title">Basic Select</h3>
31
- <div class="examples-grid">
32
- <div class="example-item">
33
- <h4>Default (Outlined)</h4>
34
- <Select
35
- v-model="basicValue"
36
- label="Select an option"
37
- :items="fruitItems"
38
- />
39
- <p class="value-display">Selected: {{ basicValue?.title || 'None' }}</p>
40
- </div>
41
-
42
- <div class="example-item">
43
- <h4>With Placeholder</h4>
44
- <Select
45
- v-model="placeholderValue"
46
- label="Favorite Fruit"
47
- placeholder="Choose a fruit..."
48
- :persistent-placeholder="true"
49
- :items="fruitItems"
50
- />
51
- </div>
52
-
53
- <div class="example-item">
54
- <h4>Clearable</h4>
55
- <Select
56
- v-model="clearableValue"
57
- label="Clearable Select"
58
- :items="fruitItems"
59
- :clearable="true"
60
- />
61
- </div>
62
-
63
- <div class="example-item">
64
- <h4>Border on Hover</h4>
65
- <Select
66
- v-model="borderHoverValue"
67
- label="Hover to see border"
68
- :items="fruitItems"
69
- :border-on-hover="true"
70
- variant="plain"
71
- />
72
- </div>
73
- </div>
74
- </div>
75
-
76
- <!-- States Section -->
77
- <div class="section">
78
- <h3 class="section-title">States</h3>
79
- <div class="examples-grid">
80
- <div class="example-item">
81
- <h4>Normal</h4>
82
- <Select
83
- v-model="normalState"
84
- label="Normal State"
85
- :items="fruitItems"
86
- />
87
- </div>
88
-
89
- <div class="example-item">
90
- <h4>Disabled</h4>
91
- <Select
92
- v-model="disabledValue"
93
- label="Disabled Select"
94
- :items="fruitItems"
95
- :disabled="true"
96
- />
97
- </div>
98
-
99
- <div class="example-item">
100
- <h4>Error</h4>
101
- <Select
102
- v-model="errorValue"
103
- label="Error State"
104
- :items="fruitItems"
105
- :error="true"
106
- />
107
- </div>
108
-
109
- <div class="example-item">
110
- <h4>Pre-selected Value</h4>
111
- <Select
112
- v-model="preselectedValue"
113
- label="Pre-selected"
114
- :items="fruitItems"
115
- />
116
- </div>
117
- </div>
118
- </div>
119
-
120
- <!-- Multiple Selection -->
121
- <div class="section">
122
- <h3 class="section-title">Multiple Selection</h3>
123
- <div class="examples-grid">
124
- <div class="example-item wide">
125
- <h4>Multiple Select</h4>
126
- <Select
127
- v-model="multipleValue"
128
- label="Select multiple options"
129
- :items="fruitItems"
130
- :multiple="true"
131
- />
132
- <p class="value-display">Selected: {{ multipleValue?.map(v => v.title).join(', ') || 'None' }}</p>
133
- </div>
134
-
135
- <div class="example-item wide">
136
- <h4>Multiple with Chips</h4>
137
- <Select
138
- v-model="chipsValue"
139
- label="Select with chips"
140
- :items="fruitItems"
141
- :multiple="true"
142
- :chips="true"
143
- />
144
- </div>
145
-
146
- <div class="example-item wide">
147
- <h4>Multiple with Closable Chips</h4>
148
- <Select
149
- v-model="closableChipsValue"
150
- label="Closable chips"
151
- :items="fruitItems"
152
- :multiple="true"
153
- :chips="true"
154
- :closable-chips="true"
155
- :clearable="true"
156
- />
157
- </div>
158
- </div>
159
- </div>
160
-
161
- <!-- Variants Section -->
162
- <div class="section">
163
- <h3 class="section-title">Variants</h3>
164
- <div class="examples-grid">
165
- <div class="example-item">
166
- <h4>Outlined (Default)</h4>
167
- <Select
168
- v-model="variantOutlined"
169
- label="Outlined"
170
- :items="fruitItems"
171
- variant="outlined"
172
- />
173
- </div>
174
-
175
- <div class="example-item">
176
- <h4>Underlined</h4>
177
- <Select
178
- v-model="variantUnderlined"
179
- label="Underlined"
180
- :items="fruitItems"
181
- variant="underlined"
182
- />
183
- </div>
184
-
185
- <div class="example-item">
186
- <h4>Filled</h4>
187
- <Select
188
- v-model="variantFilled"
189
- label="Filled"
190
- :items="fruitItems"
191
- variant="filled"
192
- />
193
- </div>
194
-
195
- <div class="example-item">
196
- <h4>Solo</h4>
197
- <Select
198
- v-model="variantSolo"
199
- label="Solo"
200
- :items="fruitItems"
201
- variant="solo"
202
- />
203
- </div>
204
-
205
- <div class="example-item">
206
- <h4>Solo Filled</h4>
207
- <Select
208
- v-model="variantSoloFilled"
209
- label="Solo Filled"
210
- :items="fruitItems"
211
- variant="solo-filled"
212
- />
213
- </div>
214
-
215
- <div class="example-item">
216
- <h4>Plain</h4>
217
- <Select
218
- v-model="variantPlain"
219
- label="Plain"
220
- :items="fruitItems"
221
- variant="plain"
222
- />
223
- </div>
224
- </div>
225
- </div>
226
-
227
- <!-- Density Section -->
228
- <div class="section">
229
- <h3 class="section-title">Density</h3>
230
- <div class="examples-grid">
231
- <div class="example-item">
232
- <h4>Default (Compact)</h4>
233
- <Select
234
- v-model="densityDefault"
235
- label="Compact"
236
- :items="fruitItems"
237
- density="compact"
238
- />
239
- </div>
240
-
241
- <div class="example-item">
242
- <h4>Comfortable</h4>
243
- <Select
244
- v-model="densityComfortable"
245
- label="Comfortable"
246
- :items="fruitItems"
247
- density="comfortable"
248
- />
249
- </div>
250
-
251
- <div class="example-item">
252
- <h4>Default Density</h4>
253
- <Select
254
- v-model="densityDefaultSize"
255
- label="Default"
256
- :items="fruitItems"
257
- density="default"
258
- />
259
- </div>
260
- </div>
261
- </div>
262
-
263
- <!-- Practical Examples -->
264
- <div class="section">
265
- <h3 class="section-title">Practical Examples</h3>
266
- <div class="examples-grid">
267
- <div class="example-item">
268
- <h4>Country Selection</h4>
269
- <Select
270
- v-model="countryValue"
271
- label="Country"
272
- placeholder="Select your country"
273
- :items="countryItems"
274
- :clearable="true"
275
- />
276
- </div>
277
-
278
- <div class="example-item">
279
- <h4>Treatment Type</h4>
280
- <Select
281
- v-model="treatmentValue"
282
- label="Behandlungsart"
283
- :items="treatmentItems"
284
- />
285
- </div>
286
-
287
- <div class="example-item wide">
288
- <h4>Multi-select Tags</h4>
289
- <Select
290
- v-model="tagsValue"
291
- label="Tags"
292
- :items="tagItems"
293
- :multiple="true"
294
- :chips="true"
295
- :closable-chips="true"
296
- :clearable="true"
297
- />
298
- </div>
299
- </div>
300
- </div>
301
-
302
- <!-- Custom Item Slot Examples -->
303
- <div class="section">
304
- <h3 class="section-title">Custom Item Slot</h3>
305
- <div class="examples-grid">
306
- <div class="example-item">
307
- <h4>Items with Icons</h4>
308
- <Select
309
- v-model="customItemValue"
310
- label="Select a fruit"
311
- :items="fruitItemsWithIcons"
312
- >
313
- <template #item="{ item, props: itemProps }">
314
- <v-list-item v-bind="itemProps">
315
- <template #prepend>
316
- <span class="item-icon">{{ item.raw.icon }}</span>
317
- </template>
318
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
319
- </v-list-item>
320
- </template>
321
- </Select>
322
- </div>
323
-
324
- <div class="example-item">
325
- <h4>Items with Description</h4>
326
- <Select
327
- v-model="customItemDescValue"
328
- label="Select a treatment"
329
- :items="treatmentItemsWithDesc"
330
- >
331
- <template #item="{ item, props: itemProps }">
332
- <v-list-item v-bind="itemProps">
333
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
334
- <v-list-item-subtitle>{{ item.raw.description }}</v-list-item-subtitle>
335
- </v-list-item>
336
- </template>
337
- </Select>
338
- </div>
339
-
340
- <div class="example-item">
341
- <h4>Items with Status Badge</h4>
342
- <Select
343
- v-model="customItemStatusValue"
344
- label="Select a patient"
345
- :items="patientItems"
346
- >
347
- <template #item="{ item, props: itemProps }">
348
- <v-list-item v-bind="itemProps">
349
- <template #prepend>
350
- <span
351
- class="status-dot"
352
- :class="item.raw.status"
353
- ></span>
354
- </template>
355
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
356
- <template #append>
357
- <span class="status-badge" :class="item.raw.status">
358
- {{ item.raw.statusLabel }}
359
- </span>
360
- </template>
361
- </v-list-item>
362
- </template>
363
- </Select>
364
- </div>
365
-
366
- <div class="example-item">
367
- <h4>Items with Custom Layout</h4>
368
- <Select
369
- v-model="customLayoutValue"
370
- label="Select a user"
371
- :items="userItems"
372
- >
373
- <template #item="{ item, props: itemProps }">
374
- <v-list-item v-bind="itemProps" class="custom-user-item">
375
- <div class="user-item-content">
376
- <div class="user-avatar">{{ item.raw.initials }}</div>
377
- <div class="user-info">
378
- <span class="user-name">{{ item.raw.title }}</span>
379
- <span class="user-email">{{ item.raw.email }}</span>
380
- </div>
381
- </div>
382
- </v-list-item>
383
- </template>
384
- </Select>
385
- </div>
386
- </div>
387
- </div>
388
-
389
- <!-- Custom Selection Slot Examples -->
390
- <div class="section">
391
- <h3 class="section-title">Custom Selection Slot</h3>
392
- <p class="section-description">Customize how selected items appear in the input field</p>
393
- <div class="examples-grid">
394
- <div class="example-item">
395
- <h4>Selection with Icon</h4>
396
- <Select
397
- v-model="selectionIconValue"
398
- label="Select a fruit"
399
- :items="fruitItemsWithIcons"
400
- :auto-select-first="true"
401
- >
402
- <template #selection="{ item }">
403
- <span class="selection-with-icon">
404
- <span class="selection-icon">{{ item.raw.icon }}</span>
405
- <span>{{ item.raw.title }}</span>
406
- </span>
407
- </template>
408
- <template #item="{ item, props: itemProps }">
409
- <v-list-item v-bind="itemProps">
410
- <template #prepend>
411
- <span class="item-icon">{{ item.raw.icon }}</span>
412
- </template>
413
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
414
- </v-list-item>
415
- </template>
416
- </Select>
417
- </div>
418
-
419
- <div class="example-item">
420
- <h4>Selection with Status</h4>
421
- <Select
422
- v-model="selectionStatusValue"
423
- label="Select a patient"
424
- :items="patientItems"
425
- >
426
- <template #selection="{ item }">
427
- <span class="selection-with-status">
428
- <span class="status-dot" :class="item.raw.status"></span>
429
- <span>{{ item.raw.title }}</span>
430
- </span>
431
- </template>
432
- <template #item="{ item, props: itemProps }">
433
- <v-list-item v-bind="itemProps">
434
- <template #prepend>
435
- <span class="status-dot" :class="item.raw.status"></span>
436
- </template>
437
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
438
- <template #append>
439
- <span class="status-badge" :class="item.raw.status">
440
- {{ item.raw.statusLabel }}
441
- </span>
442
- </template>
443
- </v-list-item>
444
- </template>
445
- </Select>
446
- </div>
447
-
448
- <div class="example-item">
449
- <h4>Selection with Avatar</h4>
450
- <Select
451
- v-model="selectionAvatarValue"
452
- label=""
453
- :items="userItems"
454
- :density="'comfortable'"
455
- menu-icon="heroicons:chevron-down"
456
- >
457
- <template #selection="{ item }">
458
- <span class="selection-with-avatar">
459
- <span class="selection-avatar">{{ item.raw.initials }}</span>
460
- <span>{{ item.raw.title }}</span>
461
- </span>
462
- </template>
463
- <template #item="{ item, props: itemProps }">
464
- <v-list-item v-bind="itemProps">
465
- <div class="user-item-content">
466
- <div class="user-avatar">{{ item.raw.initials }}</div>
467
- <div class="user-info">
468
- <span class="user-name">{{ item.raw.title }}</span>
469
- <span class="user-email">{{ item.raw.email }}</span>
470
- </div>
471
- </div>
472
- </v-list-item>
473
- </template>
474
- </Select>
475
- </div>
476
-
477
- <div class="example-item">
478
- <h4>Selection with Country Flag</h4>
479
- <Select
480
- v-model="selectionFlagValue"
481
- label="Select a country"
482
- :items="countryItemsWithFlags"
483
- >
484
- <template #selection="{ item }">
485
- <span class="selection-with-flag">
486
- <span class="country-flag">{{ item.raw.flag }}</span>
487
- <span>{{ item.raw.title }}</span>
488
- </span>
489
- </template>
490
- <template #item="{ item, props: itemProps }">
491
- <v-list-item v-bind="itemProps">
492
- <template #prepend>
493
- <span class="country-flag">{{ item.raw.flag }}</span>
494
- </template>
495
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
496
- </v-list-item>
497
- </template>
498
- </Select>
499
- </div>
500
-
501
- <div class="example-item wide">
502
- <h4>Multiple Selection with Custom Chips</h4>
503
- <Select
504
- v-model="selectionMultipleValue"
505
- label="Select fruits"
506
- :items="fruitItemsWithIcons"
507
- :multiple="true"
508
- >
509
- <template #selection="{ item, index }">
510
- <v-chip
511
- v-if="index < 3"
512
- size="small"
513
- class="custom-chip"
514
- closable
515
- @click:close="removeSelection(index)"
516
- >
517
- <span class="chip-icon">{{ item.raw.icon }}</span>
518
- {{ item.raw.title }}
519
- </v-chip>
520
- <span v-if="index === 3" class="more-indicator">
521
- (+{{ selectionMultipleValue.length - 3 }} more)
522
- </span>
523
- </template>
524
- <template #item="{ item, props: itemProps }">
525
- <v-list-item v-bind="itemProps">
526
- <template #prepend>
527
- <span class="item-icon">{{ item.raw.icon }}</span>
528
- </template>
529
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
530
- </v-list-item>
531
- </template>
532
- </Select>
533
- </div>
534
-
535
- <div class="example-item wide">
536
- <h4>Multiple Selection with Color Tags</h4>
537
- <Select
538
- v-model="selectionColorTagsValue"
539
- label="Select tags"
540
- :items="colorTagItems"
541
- :multiple="true"
542
- >
543
- <template #selection="{ item }">
544
- <span
545
- class="color-tag"
546
- :style="{ backgroundColor: item.raw.color, color: item.raw.textColor }"
547
- >
548
- {{ item.raw.title }}
549
- </span>
550
- </template>
551
- <template #item="{ item, props: itemProps }">
552
- <v-list-item v-bind="itemProps">
553
- <template #prepend>
554
- <span
555
- class="color-dot"
556
- :style="{ backgroundColor: item.raw.color }"
557
- ></span>
558
- </template>
559
- <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
560
- </v-list-item>
561
- </template>
562
- </Select>
563
- </div>
564
- </div>
565
- </div>
566
- <!-- Patient Search (Figma Design) -->
567
- <div class="section">
568
- <h3 class="section-title">Patient Search (Figma Design)</h3>
569
- <p class="section-description">Autocomplete with custom item rendering, bold matching text, and empty state</p>
570
- <div class="examples-grid">
571
- <div class="example-item">
572
- <h4>Patient Search</h4>
573
- <SelectAutocomplete
574
- v-model="patientSearchValue"
575
- label=""
576
- placeholder="Gebe den Patienten Namen ein"
577
- :persistent-placeholder="true"
578
- :items="patientSearchItems"
579
- :clearable="true"
580
- clear-icon="mdi-close"
581
- :return-object="true"
582
- item-title="name"
583
- item-value="id"
584
- :auto-select-first="true"
585
- :custom-filter="patientFilter"
586
- @update:search="onPatientSearch"
587
- >
588
- <template #append-inner>
589
- <svg v-if="!patientSearchQuery" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
590
- </template>
591
- <template #item="{ item, props: itemProps }">
592
- <v-list-item v-bind="itemProps" :title="undefined" class="patient-search-item">
593
- <template #default>
594
- <div class="patient-row">
595
- <div class="patient-left">
596
- <span class="patient-name" v-html="highlightMatch(item.raw.name, patientSearchQuery)"></span>
597
- <span class="patient-id">#{{ item.raw.patientId }}</span>
598
- </div>
599
- <span class="patient-dob">{{ item.raw.dob }}</span>
600
- </div>
601
- </template>
602
- </v-list-item>
603
- </template>
604
- <template #no-data>
605
- <div class="patient-no-data">
606
- <p class="patient-no-data-title">Kein Patient gefunden</p>
607
- <p class="patient-no-data-desc">Bitte überprüfen Sie die Eingabe oder versuchen Sie es mit einem anderen Namen.</p>
608
- <button class="patient-add-btn" @click="onAddPatient">Neuen Patienten hinzufügen</button>
609
- </div>
610
- </template>
611
- </SelectAutocomplete>
612
- <div v-if="patientSearchValue" class="patient-selected-display">
613
- <div class="patient-selected-info">
614
- <span class="patient-selected-name">{{ patientSearchValue.name }}</span>
615
- <span class="patient-selected-meta">#{{ patientSearchValue.patientId }}, {{ patientSearchValue.dob }}</span>
616
- </div>
617
- <button class="patient-edit-btn" @click="patientSearchValue = null">
618
- <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>
619
- </button>
620
- </div>
621
- </div>
622
- </div>
623
- </div>
624
-
625
- <!-- SelectAutocomplete Section -->
626
- <div class="section">
627
- <h3 class="section-title">SelectAutocomplete</h3>
628
- <p class="section-description">Searchable select with autocomplete filtering</p>
629
- <div class="examples-grid">
630
- <div class="example-item">
631
- <h4>Default</h4>
632
- <SelectAutocomplete
633
- v-model="autocompleteBasicValue"
634
- label="Search a fruit"
635
- :items="fruitItems"
636
- />
637
- <p class="value-display">Selected: {{ autocompleteBasicValue?.title || 'None' }}</p>
638
- </div>
639
-
640
- <div class="example-item">
641
- <h4>With Placeholder</h4>
642
- <SelectAutocomplete
643
- v-model="autocompletePlaceholderValue"
644
- label="Treatment"
645
- placeholder="Type to search..."
646
- :persistent-placeholder="true"
647
- :items="treatmentItems"
648
- />
649
- </div>
650
-
651
- <div class="example-item">
652
- <h4>Clearable</h4>
653
- <SelectAutocomplete
654
- v-model="autocompleteClearableValue"
655
- label="Clearable Autocomplete"
656
- :items="fruitItems"
657
- :clearable="true"
658
- />
659
- </div>
660
-
661
- <div class="example-item">
662
- <h4>Disabled</h4>
663
- <SelectAutocomplete
664
- v-model="autocompleteDisabledValue"
665
- label="Disabled Autocomplete"
666
- :items="fruitItems"
667
- :disabled="true"
668
- />
669
- </div>
670
-
671
- <div class="example-item">
672
- <h4>Error State</h4>
673
- <SelectAutocomplete
674
- v-model="autocompleteErrorValue"
675
- label="Error Autocomplete"
676
- :items="fruitItems"
677
- :error="true"
678
- />
679
- </div>
680
-
681
- <div class="example-item">
682
- <h4>Country Search</h4>
683
- <SelectAutocomplete
684
- v-model="autocompleteCountryValue"
685
- label="Country"
686
- placeholder="Search country..."
687
- :items="countryItems"
688
- :clearable="true"
689
- />
690
- </div>
691
-
692
- <div class="example-item wide">
693
- <h4>Multiple with Chips</h4>
694
- <SelectAutocomplete
695
- v-model="autocompleteMultipleValue"
696
- label="Select multiple"
697
- :items="tagItems"
698
- :multiple="true"
699
- :chips="true"
700
- :closable-chips="true"
701
- :clearable="true"
702
- />
703
- <p class="value-display">Selected: {{ autocompleteMultipleValue?.map(v => v.title).join(', ') || 'None' }}</p>
704
- </div>
705
- </div>
706
- </div>
707
- </div>
708
- </div>
709
- </template>
710
-
711
- <script setup lang="ts">
712
- import { computed, ref } from "vue";
713
- import {
714
- domain,
715
- setTestingDomain,
716
- clearTestingDomain,
717
- } from "@/utils/index";
718
-
719
- import Select from "@/components/Select/Select.vue";
720
- import SelectAutocomplete from "@/components/SelectAutocomplete/SelectAutocomplete.vue";
721
- import ListItem from "@/components/ListItem/ListItem.vue";
722
- import { avatarPlaceholder } from "..";
723
-
724
- const currentDomain = computed(() => domain.value);
725
-
726
- const switchToDental = () => {
727
- setTestingDomain("domain-dental");
728
- };
729
-
730
- const switchToCocoon = () => {
731
- setTestingDomain("domain-cocoon");
732
- };
733
-
734
- const resetDomain = () => {
735
- clearTestingDomain();
736
- };
737
-
738
- // Sample items
739
- const fruitItems = [
740
- { title: 'Apple', value: 'apple' },
741
- { title: 'Banana', value: 'banana' },
742
- { title: 'Cherry', value: 'cherry' },
743
- { title: 'Orange', value: 'orange' },
744
- { title: 'Strawberry', value: 'strawberry' },
745
- ];
746
-
747
- const countryItems = [
748
- { title: 'Deutschland', value: 'de' },
749
- { title: 'Österreich', value: 'at' },
750
- { title: 'Schweiz', value: 'ch' },
751
- { title: 'Frankreich', value: 'fr' },
752
- { title: 'Italien', value: 'it' },
753
- ];
754
-
755
- const treatmentItems = [
756
- { title: 'Zahnreinigung', value: 'cleaning' },
757
- { title: 'Kontrolluntersuchung', value: 'checkup' },
758
- { title: 'Implantologie', value: 'implant' },
759
- { title: 'Kieferorthopädie', value: 'ortho' },
760
- { title: 'Wurzelbehandlung', value: 'root' },
761
- ];
762
-
763
- const tagItems = [
764
- { title: 'Urgent', value: 'urgent' },
765
- { title: 'Follow-up', value: 'followup' },
766
- { title: 'New Patient', value: 'new' },
767
- { title: 'VIP', value: 'vip' },
768
- { title: 'Insurance Pending', value: 'insurance' },
769
- ];
770
-
771
- // Patient search items (Figma design)
772
- const patientSearchItems = [
773
- { name: 'Weber, Wolfgang', patientId: '06432', dob: '12.09.2001', id: '1' },
774
- { name: 'Krause, Wolfram', patientId: '26152', dob: '12.04.1954', id: '2' },
775
- { name: 'Wolff, Wolfhard', patientId: '82692', dob: '15.05.1953', id: '3' },
776
- { name: 'Adler, Wolfbert', patientId: '83827', dob: '12.09.2000', id: '4' },
777
- { name: 'Schulz, Wolfgang', patientId: '72376', dob: '05.12.1987', id: '5' },
778
- ];
779
-
780
- // Custom item slot examples
781
- const fruitItemsWithIcons = [
782
- { title: 'Apple', value: 'apple', icon: '🍎' },
783
- { title: 'Banana', value: 'banana', icon: '🍌' },
784
- { title: 'Cherry', value: 'cherry', icon: '🍒' },
785
- { title: 'Orange', value: 'orange', icon: '🍊' },
786
- { title: 'Strawberry', value: 'strawberry', icon: '🍓' },
787
- ];
788
-
789
- const treatmentItemsWithDesc = [
790
- { title: 'Zahnreinigung', value: 'cleaning', description: 'Professionelle Reinigung und Politur' },
791
- { title: 'Kontrolluntersuchung', value: 'checkup', description: 'Regelmäßige Kontrolle der Zahngesundheit' },
792
- { title: 'Implantologie', value: 'implant', description: 'Ersatz fehlender Zähne durch Implantate' },
793
- { title: 'Wurzelbehandlung', value: 'root', description: 'Behandlung des Zahnmarks' },
794
- ];
795
-
796
- const patientItems = [
797
- { title: 'Max Mustermann', value: 'max', status: 'active', statusLabel: 'Aktiv' },
798
- { title: 'Anna Schmidt', value: 'anna', status: 'waiting', statusLabel: 'Wartend' },
799
- { title: 'Peter Weber', value: 'peter', status: 'inactive', statusLabel: 'Inaktiv' },
800
- { title: 'Lisa Müller', value: 'lisa', status: 'active', statusLabel: 'Aktiv' },
801
- ];
802
-
803
- const userItems = [
804
- { title: 'Dr. Maria Schmidt', value: 'maria', initials: 'MS', email: 'maria@praxis.de' },
805
- { title: 'Dr. Thomas Bauer', value: 'thomas', initials: 'TB', email: 'thomas@praxis.de' },
806
- { title: 'Julia Fischer', value: 'julia', initials: 'JF', email: 'julia@praxis.de' },
807
- ];
808
-
809
- // Custom selection slot examples
810
- const countryItemsWithFlags = [
811
- { title: 'Deutschland', value: 'de', flag: '🇩🇪' },
812
- { title: 'Österreich', value: 'at', flag: '🇦🇹' },
813
- { title: 'Schweiz', value: 'ch', flag: '🇨🇭' },
814
- { title: 'Frankreich', value: 'fr', flag: '🇫🇷' },
815
- { title: 'Italien', value: 'it', flag: '🇮🇹' },
816
- ];
817
-
818
- const colorTagItems = [
819
- { title: 'High Priority', value: 'high', color: '#ef4444', textColor: '#ffffff' },
820
- { title: 'Medium Priority', value: 'medium', color: '#f59e0b', textColor: '#ffffff' },
821
- { title: 'Low Priority', value: 'low', color: '#22c55e', textColor: '#ffffff' },
822
- { title: 'On Hold', value: 'hold', color: '#6b7280', textColor: '#ffffff' },
823
- { title: 'In Progress', value: 'progress', color: '#3b82f6', textColor: '#ffffff' },
824
- ];
825
-
826
- // Basic examples
827
- const basicValue = ref(null);
828
- const placeholderValue = ref(null);
829
- const clearableValue = ref(null);
830
- const borderHoverValue = ref(null);
831
-
832
- // States
833
- const normalState = ref(null);
834
- const disabledValue = ref({ title: 'Apple', value: 'apple' });
835
- const errorValue = ref(null);
836
- const preselectedValue = ref({ title: 'Cherry', value: 'cherry' });
837
-
838
- // Multiple selection
839
- const multipleValue = ref([]);
840
- const chipsValue = ref([]);
841
- const closableChipsValue = ref([
842
- { title: 'Apple', value: 'apple' },
843
- { title: 'Cherry', value: 'cherry' },
844
- ]);
845
-
846
- // Variants
847
- const variantOutlined = ref(null);
848
- const variantUnderlined = ref(null);
849
- const variantFilled = ref(null);
850
- const variantSolo = ref(null);
851
- const variantSoloFilled = ref(null);
852
- const variantPlain = ref(null);
853
-
854
- // Density
855
- const densityDefault = ref(null);
856
- const densityComfortable = ref(null);
857
- const densityDefaultSize = ref(null);
858
-
859
- // Practical examples
860
- const countryValue = ref(null);
861
- const treatmentValue = ref(null);
862
- const tagsValue = ref([]);
863
-
864
- // Patient search (Figma design)
865
- const patientSearchValue = ref(null);
866
- const patientSearchQuery = ref('');
867
-
868
- const patientFilter = (_value: string, query: string, item: any) => {
869
- if (!query) return true;
870
- const q = query.toLowerCase();
871
- const raw = item.raw;
872
- return (
873
- raw.name?.toLowerCase().includes(q) ||
874
- raw.patientId?.toLowerCase().includes(q) ||
875
- raw.dob?.toLowerCase().includes(q)
876
- );
877
- };
878
-
879
- const onPatientSearch = (val: string) => {
880
- patientSearchQuery.value = val || '';
881
- };
882
-
883
- const highlightMatch = (text: string, query: string): string => {
884
- if (!query) return text;
885
- const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
886
- const regex = new RegExp(`(${escaped})`, 'gi');
887
- return text.replace(regex, '<strong>$1</strong>');
888
- };
889
-
890
- const onAddPatient = () => {
891
- alert('Neuen Patienten hinzufügen');
892
- };
893
-
894
- // Custom item slot examples
895
- const customItemValue = ref(null);
896
- const customItemDescValue = ref(null);
897
- const customItemStatusValue = ref(null);
898
- const customLayoutValue = ref(null);
899
-
900
- // Custom selection slot examples
901
- const selectionIconValue = ref(null);
902
- const selectionStatusValue = ref(null);
903
- const selectionAvatarValue = ref(null);
904
- const selectionFlagValue = ref(null);
905
- const selectionMultipleValue = ref([]);
906
- const selectionColorTagsValue = ref([]);
907
-
908
- const removeSelection = (index: number) => {
909
- selectionMultipleValue.value.splice(index, 1);
910
- };
911
- </script>
912
-
913
- <style scoped>
914
- .page {
915
- display: flex;
916
- flex-direction: column;
917
- justify-content: flex-start;
918
- align-items: center;
919
- width: 100vw;
920
- min-height: 100vh;
921
- background-color: #f5f5f5;
922
- padding: 2rem 0;
923
- overflow-y: auto;
924
- }
925
-
926
- .element-container {
927
- display: flex;
928
- flex-direction: column;
929
- justify-content: flex-start;
930
- align-items: center;
931
- width: 95%;
932
- max-width: 1400px;
933
- gap: 2rem;
934
- }
935
-
936
- .controls {
937
- width: 100%;
938
- background: white;
939
- padding: 1.5rem;
940
- border-radius: 8px;
941
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
942
- text-align: center;
943
- }
944
-
945
- .controls h2 {
946
- margin: 0 0 1rem 0;
947
- color: #333;
948
- font-size: 1.5rem;
949
- }
950
-
951
- .button-group {
952
- display: flex;
953
- gap: 1rem;
954
- justify-content: center;
955
- flex-wrap: wrap;
956
- }
957
-
958
- .control-btn {
959
- padding: 0.75rem 1.5rem;
960
- font-size: 1rem;
961
- border: none;
962
- border-radius: 6px;
963
- cursor: pointer;
964
- background-color: #4caf50;
965
- color: white;
966
- transition: background-color 0.3s ease;
967
- font-weight: 500;
968
- }
969
-
970
- .control-btn:hover {
971
- background-color: #45a049;
972
- }
973
-
974
- .control-btn.reset {
975
- background-color: #f44336;
976
- }
977
-
978
- .control-btn.reset:hover {
979
- background-color: #da190b;
980
- }
981
-
982
- .section {
983
- width: 100%;
984
- background: white;
985
- padding: 1.5rem;
986
- border-radius: 8px;
987
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
988
- }
989
-
990
- .section-title {
991
- margin: 0 0 1.5rem 0;
992
- color: #333;
993
- font-size: 1.25rem;
994
- font-weight: 600;
995
- border-bottom: 2px solid #e0e0e0;
996
- padding-bottom: 0.5rem;
997
- }
998
-
999
- .examples-grid {
1000
- display: grid;
1001
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
1002
- gap: 1.5rem;
1003
- }
1004
-
1005
- .example-item {
1006
- display: flex;
1007
- flex-direction: column;
1008
- gap: 0.5rem;
1009
- }
1010
-
1011
- .example-item.wide {
1012
- grid-column: span 2;
1013
- }
1014
-
1015
- .example-item h4 {
1016
- margin: 0;
1017
- font-size: 0.875rem;
1018
- font-weight: 600;
1019
- color: #555;
1020
- }
1021
-
1022
- .value-display {
1023
- margin: 0.5rem 0 0 0;
1024
- font-size: 0.8125rem;
1025
- color: #666;
1026
- font-style: italic;
1027
- }
1028
-
1029
- @media (max-width: 768px) {
1030
- .examples-grid {
1031
- grid-template-columns: 1fr;
1032
- }
1033
-
1034
- .example-item.wide {
1035
- grid-column: span 1;
1036
- }
1037
- }
1038
-
1039
- /* Custom item slot styles */
1040
- .item-icon {
1041
- font-size: 1.25rem;
1042
- margin-right: 0.5rem;
1043
- }
1044
-
1045
- .status-dot {
1046
- width: 10px;
1047
- height: 10px;
1048
- border-radius: 50%;
1049
- margin-right: 0.5rem;
1050
- }
1051
-
1052
- .status-dot.active {
1053
- background-color: #4caf50;
1054
- }
1055
-
1056
- .status-dot.waiting {
1057
- background-color: #ff9800;
1058
- }
1059
-
1060
- .status-dot.inactive {
1061
- background-color: #9e9e9e;
1062
- }
1063
-
1064
- .status-badge {
1065
- font-size: 0.75rem;
1066
- padding: 0.125rem 0.5rem;
1067
- border-radius: 999px;
1068
- font-weight: 500;
1069
- }
1070
-
1071
- .status-badge.active {
1072
- background-color: #e8f5e9;
1073
- color: #2e7d32;
1074
- }
1075
-
1076
- .status-badge.waiting {
1077
- background-color: #fff3e0;
1078
- color: #ef6c00;
1079
- }
1080
-
1081
- .status-badge.inactive {
1082
- background-color: #f5f5f5;
1083
- color: #757575;
1084
- }
1085
-
1086
- .user-item-content {
1087
- display: flex;
1088
- align-items: center;
1089
- gap: 0.75rem;
1090
- padding: 0.25rem 0;
1091
- }
1092
-
1093
- .user-avatar {
1094
- width: 36px;
1095
- height: 36px;
1096
- border-radius: 50%;
1097
- background-color: #172774;
1098
- color: white;
1099
- display: flex;
1100
- align-items: center;
1101
- justify-content: center;
1102
- font-size: 0.875rem;
1103
- font-weight: 600;
1104
- }
1105
-
1106
- .user-info {
1107
- display: flex;
1108
- flex-direction: column;
1109
- }
1110
-
1111
- .user-name {
1112
- font-weight: 500;
1113
- color: #333;
1114
- }
1115
-
1116
- .user-email {
1117
- font-size: 0.75rem;
1118
- color: #666;
1119
- }
1120
-
1121
- /* Section description */
1122
- .section-description {
1123
- margin: -1rem 0 1.5rem 0;
1124
- font-size: 0.875rem;
1125
- color: #666;
1126
- }
1127
-
1128
- /* Custom selection slot styles */
1129
- .selection-with-icon,
1130
- .selection-with-status,
1131
- .selection-with-avatar,
1132
- .selection-with-flag {
1133
- display: inline-flex;
1134
- align-items: center;
1135
- gap: 0.5rem;
1136
- }
1137
-
1138
- .selection-icon {
1139
- font-size: 1.125rem;
1140
- }
1141
-
1142
- .selection-avatar {
1143
- width: 24px;
1144
- height: 24px;
1145
- border-radius: 50%;
1146
- background-color: #172774;
1147
- color: white;
1148
- display: inline-flex;
1149
- align-items: center;
1150
- justify-content: center;
1151
- font-size: 0.625rem;
1152
- font-weight: 600;
1153
- }
1154
-
1155
- .country-flag {
1156
- font-size: 1.25rem;
1157
- margin-right: 0.25rem;
1158
- }
1159
-
1160
- .custom-chip {
1161
- margin: 2px;
1162
- }
1163
-
1164
- .chip-icon {
1165
- margin-right: 0.25rem;
1166
- }
1167
-
1168
- .more-indicator {
1169
- font-size: 0.75rem;
1170
- color: #666;
1171
- margin-left: 0.25rem;
1172
- }
1173
-
1174
- .color-tag {
1175
- display: inline-block;
1176
- padding: 0.125rem 0.5rem;
1177
- border-radius: 4px;
1178
- font-size: 0.75rem;
1179
- font-weight: 500;
1180
- margin: 2px;
1181
- }
1182
-
1183
- .color-dot {
1184
- width: 12px;
1185
- height: 12px;
1186
- border-radius: 50%;
1187
- margin-right: 0.5rem;
1188
- }
1189
-
1190
- /* Patient Search (Figma Design) styles */
1191
- .patient-row {
1192
- display: flex;
1193
- justify-content: space-between;
1194
- align-items: flex-start;
1195
- width: 100%;
1196
- padding: 0.375rem 0;
1197
- }
1198
-
1199
- .patient-left {
1200
- display: flex;
1201
- flex-direction: column;
1202
- gap: 0.125rem;
1203
- }
1204
-
1205
- .patient-name {
1206
- font-size: 0.9375rem;
1207
- font-weight: 400;
1208
- color: var(--Dental-Blue-0, #172774);
1209
- }
1210
-
1211
- .patient-id {
1212
- font-size: 0.75rem;
1213
- color: var(--Soft-Concrete-2, #9e9e9e);
1214
- }
1215
-
1216
- .patient-dob {
1217
- font-size: 0.875rem;
1218
- color: var(--Dental-Blue-0, #172774);
1219
- white-space: nowrap;
1220
- margin-left: 1rem;
1221
- }
1222
-
1223
- .patient-no-data {
1224
- display: flex;
1225
- flex-direction: column;
1226
- align-items: center;
1227
- padding: 1.5rem 1rem;
1228
- text-align: center;
1229
- }
1230
-
1231
- .patient-no-data-title {
1232
- font-size: 0.9375rem;
1233
- font-weight: 600;
1234
- color: var(--Dental-Blue-0, #172774);
1235
- margin: 0 0 0.5rem 0;
1236
- }
1237
-
1238
- .patient-no-data-desc {
1239
- font-size: 0.8125rem;
1240
- color: var(--Soft-Concrete-2, #9e9e9e);
1241
- margin: 0 0 1rem 0;
1242
- max-width: 260px;
1243
- line-height: 1.4;
1244
- }
1245
-
1246
- .patient-add-btn {
1247
- background: none;
1248
- border: 1.5px solid var(--Dental-Blue-0, #172774);
1249
- color: var(--Dental-Blue-0, #172774);
1250
- border-radius: 999px;
1251
- padding: 0.5rem 1.25rem;
1252
- font-size: 0.875rem;
1253
- font-weight: 500;
1254
- cursor: pointer;
1255
- transition: background-color 0.2s;
1256
- }
1257
-
1258
- .patient-add-btn:hover {
1259
- background-color: rgba(23, 39, 116, 0.05);
1260
- }
1261
-
1262
- .patient-selected-display {
1263
- display: flex;
1264
- justify-content: space-between;
1265
- align-items: center;
1266
- margin-top: 0.75rem;
1267
- padding: 0 0.25rem;
1268
- }
1269
-
1270
- .patient-selected-info {
1271
- display: flex;
1272
- flex-direction: column;
1273
- gap: 0.125rem;
1274
- }
1275
-
1276
- .patient-selected-name {
1277
- font-size: 0.9375rem;
1278
- font-weight: 500;
1279
- color: var(--Dental-Blue-0, #172774);
1280
- }
1281
-
1282
- .patient-selected-meta {
1283
- font-size: 0.75rem;
1284
- color: var(--Soft-Concrete-2, #9e9e9e);
1285
- }
1286
-
1287
- .patient-edit-btn {
1288
- background: none;
1289
- border: none;
1290
- cursor: pointer;
1291
- color: var(--Dental-Blue-0, #172774);
1292
- padding: 0.25rem;
1293
- border-radius: 4px;
1294
- display: flex;
1295
- align-items: center;
1296
- justify-content: center;
1297
- }
1298
-
1299
- .patient-edit-btn:hover {
1300
- background-color: rgba(23, 39, 116, 0.05);
1301
- }
1302
- </style>
1
+ <template>
2
+ <div class="page">
3
+ <div class="element-container">
4
+ <div class="controls">
5
+ <h2>Testing Domain: {{ currentDomain }}</h2>
6
+ <div class="button-group">
7
+ <button
8
+ @click="switchToDental"
9
+ class="control-btn"
10
+ >
11
+ Switch to Wunschlachen (Dental)
12
+ </button>
13
+ <button
14
+ @click="switchToCocoon"
15
+ class="control-btn"
16
+ >
17
+ Switch to White Cocoon
18
+ </button>
19
+ <button
20
+ @click="resetDomain"
21
+ class="control-btn reset"
22
+ >
23
+ Reset to Auto-Detect
24
+ </button>
25
+ </div>
26
+ </div>
27
+
28
+ <!-- Basic Select Examples -->
29
+ <div class="section">
30
+ <h3 class="section-title">Basic Select</h3>
31
+ <div class="examples-grid">
32
+ <div class="example-item">
33
+ <h4>Default (Outlined)</h4>
34
+ <Select
35
+ v-model="basicValue"
36
+ label="Select an option"
37
+ :items="fruitItems"
38
+ />
39
+ <p class="value-display">Selected: {{ basicValue?.title || 'None' }}</p>
40
+ </div>
41
+
42
+ <div class="example-item">
43
+ <h4>With Placeholder</h4>
44
+ <Select
45
+ v-model="placeholderValue"
46
+ label="Favorite Fruit"
47
+ placeholder="Choose a fruit..."
48
+ :persistent-placeholder="true"
49
+ :items="fruitItems"
50
+ />
51
+ </div>
52
+
53
+ <div class="example-item">
54
+ <h4>Clearable</h4>
55
+ <Select
56
+ v-model="clearableValue"
57
+ label="Clearable Select"
58
+ :items="fruitItems"
59
+ :clearable="true"
60
+ />
61
+ </div>
62
+
63
+ <div class="example-item">
64
+ <h4>Border on Hover</h4>
65
+ <Select
66
+ v-model="borderHoverValue"
67
+ label="Hover to see border"
68
+ :items="fruitItems"
69
+ :border-on-hover="true"
70
+ variant="plain"
71
+ />
72
+ </div>
73
+ </div>
74
+ </div>
75
+
76
+ <!-- States Section -->
77
+ <div class="section">
78
+ <h3 class="section-title">States</h3>
79
+ <div class="examples-grid">
80
+ <div class="example-item">
81
+ <h4>Normal</h4>
82
+ <Select
83
+ v-model="normalState"
84
+ label="Normal State"
85
+ :items="fruitItems"
86
+ />
87
+ </div>
88
+
89
+ <div class="example-item">
90
+ <h4>Disabled</h4>
91
+ <Select
92
+ v-model="disabledValue"
93
+ label="Disabled Select"
94
+ :items="fruitItems"
95
+ :disabled="true"
96
+ />
97
+ </div>
98
+
99
+ <div class="example-item">
100
+ <h4>Error</h4>
101
+ <Select
102
+ v-model="errorValue"
103
+ label="Error State"
104
+ :items="fruitItems"
105
+ :error="true"
106
+ />
107
+ </div>
108
+
109
+ <div class="example-item">
110
+ <h4>Pre-selected Value</h4>
111
+ <Select
112
+ v-model="preselectedValue"
113
+ label="Pre-selected"
114
+ :items="fruitItems"
115
+ />
116
+ </div>
117
+ </div>
118
+ </div>
119
+
120
+ <!-- Multiple Selection -->
121
+ <div class="section">
122
+ <h3 class="section-title">Multiple Selection</h3>
123
+ <div class="examples-grid">
124
+ <div class="example-item wide">
125
+ <h4>Multiple Select</h4>
126
+ <Select
127
+ v-model="multipleValue"
128
+ label="Select multiple options"
129
+ :items="fruitItems"
130
+ :multiple="true"
131
+ />
132
+ <p class="value-display">Selected: {{ multipleValue?.map(v => v.title).join(', ') || 'None' }}</p>
133
+ </div>
134
+
135
+ <div class="example-item wide">
136
+ <h4>Multiple with Chips</h4>
137
+ <Select
138
+ v-model="chipsValue"
139
+ label="Select with chips"
140
+ :items="fruitItems"
141
+ :multiple="true"
142
+ :chips="true"
143
+ />
144
+ </div>
145
+
146
+ <div class="example-item wide">
147
+ <h4>Multiple with Closable Chips</h4>
148
+ <Select
149
+ v-model="closableChipsValue"
150
+ label="Closable chips"
151
+ :items="fruitItems"
152
+ :multiple="true"
153
+ :chips="true"
154
+ :closable-chips="true"
155
+ :clearable="true"
156
+ />
157
+ </div>
158
+ </div>
159
+ </div>
160
+
161
+ <!-- Variants Section -->
162
+ <div class="section">
163
+ <h3 class="section-title">Variants</h3>
164
+ <div class="examples-grid">
165
+ <div class="example-item">
166
+ <h4>Outlined (Default)</h4>
167
+ <Select
168
+ v-model="variantOutlined"
169
+ label="Outlined"
170
+ :items="fruitItems"
171
+ variant="outlined"
172
+ />
173
+ </div>
174
+
175
+ <div class="example-item">
176
+ <h4>Underlined</h4>
177
+ <Select
178
+ v-model="variantUnderlined"
179
+ label="Underlined"
180
+ :items="fruitItems"
181
+ variant="underlined"
182
+ />
183
+ </div>
184
+
185
+ <div class="example-item">
186
+ <h4>Filled</h4>
187
+ <Select
188
+ v-model="variantFilled"
189
+ label="Filled"
190
+ :items="fruitItems"
191
+ variant="filled"
192
+ />
193
+ </div>
194
+
195
+ <div class="example-item">
196
+ <h4>Solo</h4>
197
+ <Select
198
+ v-model="variantSolo"
199
+ label="Solo"
200
+ :items="fruitItems"
201
+ variant="solo"
202
+ />
203
+ </div>
204
+
205
+ <div class="example-item">
206
+ <h4>Solo Filled</h4>
207
+ <Select
208
+ v-model="variantSoloFilled"
209
+ label="Solo Filled"
210
+ :items="fruitItems"
211
+ variant="solo-filled"
212
+ />
213
+ </div>
214
+
215
+ <div class="example-item">
216
+ <h4>Plain</h4>
217
+ <Select
218
+ v-model="variantPlain"
219
+ label="Plain"
220
+ :items="fruitItems"
221
+ variant="plain"
222
+ />
223
+ </div>
224
+ </div>
225
+ </div>
226
+
227
+ <!-- Density Section -->
228
+ <div class="section">
229
+ <h3 class="section-title">Density</h3>
230
+ <div class="examples-grid">
231
+ <div class="example-item">
232
+ <h4>Default (Compact)</h4>
233
+ <Select
234
+ v-model="densityDefault"
235
+ label="Compact"
236
+ :items="fruitItems"
237
+ density="compact"
238
+ />
239
+ </div>
240
+
241
+ <div class="example-item">
242
+ <h4>Comfortable</h4>
243
+ <Select
244
+ v-model="densityComfortable"
245
+ label="Comfortable"
246
+ :items="fruitItems"
247
+ density="comfortable"
248
+ />
249
+ </div>
250
+
251
+ <div class="example-item">
252
+ <h4>Default Density</h4>
253
+ <Select
254
+ v-model="densityDefaultSize"
255
+ label="Default"
256
+ :items="fruitItems"
257
+ density="default"
258
+ />
259
+ </div>
260
+ </div>
261
+ </div>
262
+
263
+ <!-- Practical Examples -->
264
+ <div class="section">
265
+ <h3 class="section-title">Practical Examples</h3>
266
+ <div class="examples-grid">
267
+ <div class="example-item">
268
+ <h4>Country Selection</h4>
269
+ <Select
270
+ v-model="countryValue"
271
+ label="Country"
272
+ placeholder="Select your country"
273
+ :items="countryItems"
274
+ :clearable="true"
275
+ />
276
+ </div>
277
+
278
+ <div class="example-item">
279
+ <h4>Treatment Type</h4>
280
+ <Select
281
+ v-model="treatmentValue"
282
+ label="Behandlungsart"
283
+ :items="treatmentItems"
284
+ />
285
+ </div>
286
+
287
+ <div class="example-item wide">
288
+ <h4>Multi-select Tags</h4>
289
+ <Select
290
+ v-model="tagsValue"
291
+ label="Tags"
292
+ :items="tagItems"
293
+ :multiple="true"
294
+ :chips="true"
295
+ :closable-chips="true"
296
+ :clearable="true"
297
+ />
298
+ </div>
299
+ </div>
300
+ </div>
301
+
302
+ <!-- Custom Item Slot Examples -->
303
+ <div class="section">
304
+ <h3 class="section-title">Custom Item Slot</h3>
305
+ <div class="examples-grid">
306
+ <div class="example-item">
307
+ <h4>Items with Icons</h4>
308
+ <Select
309
+ v-model="customItemValue"
310
+ label="Select a fruit"
311
+ :items="fruitItemsWithIcons"
312
+ >
313
+ <template #item="{ item, props: itemProps }">
314
+ <v-list-item v-bind="itemProps">
315
+ <template #prepend>
316
+ <span class="item-icon">{{ item.raw.icon }}</span>
317
+ </template>
318
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
319
+ </v-list-item>
320
+ </template>
321
+ </Select>
322
+ </div>
323
+
324
+ <div class="example-item">
325
+ <h4>Items with Description</h4>
326
+ <Select
327
+ v-model="customItemDescValue"
328
+ label="Select a treatment"
329
+ :items="treatmentItemsWithDesc"
330
+ >
331
+ <template #item="{ item, props: itemProps }">
332
+ <v-list-item v-bind="itemProps">
333
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
334
+ <v-list-item-subtitle>{{ item.raw.description }}</v-list-item-subtitle>
335
+ </v-list-item>
336
+ </template>
337
+ </Select>
338
+ </div>
339
+
340
+ <div class="example-item">
341
+ <h4>Items with Status Badge</h4>
342
+ <Select
343
+ v-model="customItemStatusValue"
344
+ label="Select a patient"
345
+ :items="patientItems"
346
+ >
347
+ <template #item="{ item, props: itemProps }">
348
+ <v-list-item v-bind="itemProps">
349
+ <template #prepend>
350
+ <span
351
+ class="status-dot"
352
+ :class="item.raw.status"
353
+ ></span>
354
+ </template>
355
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
356
+ <template #append>
357
+ <span class="status-badge" :class="item.raw.status">
358
+ {{ item.raw.statusLabel }}
359
+ </span>
360
+ </template>
361
+ </v-list-item>
362
+ </template>
363
+ </Select>
364
+ </div>
365
+
366
+ <div class="example-item">
367
+ <h4>Items with Custom Layout</h4>
368
+ <Select
369
+ v-model="customLayoutValue"
370
+ label="Select a user"
371
+ :items="userItems"
372
+ >
373
+ <template #item="{ item, props: itemProps }">
374
+ <v-list-item v-bind="itemProps" class="custom-user-item">
375
+ <div class="user-item-content">
376
+ <div class="user-avatar">{{ item.raw.initials }}</div>
377
+ <div class="user-info">
378
+ <span class="user-name">{{ item.raw.title }}</span>
379
+ <span class="user-email">{{ item.raw.email }}</span>
380
+ </div>
381
+ </div>
382
+ </v-list-item>
383
+ </template>
384
+ </Select>
385
+ </div>
386
+ </div>
387
+ </div>
388
+
389
+ <!-- Custom Selection Slot Examples -->
390
+ <div class="section">
391
+ <h3 class="section-title">Custom Selection Slot</h3>
392
+ <p class="section-description">Customize how selected items appear in the input field</p>
393
+ <div class="examples-grid">
394
+ <div class="example-item">
395
+ <h4>Selection with Icon</h4>
396
+ <Select
397
+ v-model="selectionIconValue"
398
+ label="Select a fruit"
399
+ :items="fruitItemsWithIcons"
400
+ :auto-select-first="true"
401
+ >
402
+ <template #selection="{ item }">
403
+ <span class="selection-with-icon">
404
+ <span class="selection-icon">{{ item.raw.icon }}</span>
405
+ <span>{{ item.raw.title }}</span>
406
+ </span>
407
+ </template>
408
+ <template #item="{ item, props: itemProps }">
409
+ <v-list-item v-bind="itemProps">
410
+ <template #prepend>
411
+ <span class="item-icon">{{ item.raw.icon }}</span>
412
+ </template>
413
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
414
+ </v-list-item>
415
+ </template>
416
+ </Select>
417
+ </div>
418
+
419
+ <div class="example-item">
420
+ <h4>Selection with Status</h4>
421
+ <Select
422
+ v-model="selectionStatusValue"
423
+ label="Select a patient"
424
+ :items="patientItems"
425
+ >
426
+ <template #selection="{ item }">
427
+ <span class="selection-with-status">
428
+ <span class="status-dot" :class="item.raw.status"></span>
429
+ <span>{{ item.raw.title }}</span>
430
+ </span>
431
+ </template>
432
+ <template #item="{ item, props: itemProps }">
433
+ <v-list-item v-bind="itemProps">
434
+ <template #prepend>
435
+ <span class="status-dot" :class="item.raw.status"></span>
436
+ </template>
437
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
438
+ <template #append>
439
+ <span class="status-badge" :class="item.raw.status">
440
+ {{ item.raw.statusLabel }}
441
+ </span>
442
+ </template>
443
+ </v-list-item>
444
+ </template>
445
+ </Select>
446
+ </div>
447
+
448
+ <div class="example-item">
449
+ <h4>Selection with Avatar</h4>
450
+ <Select
451
+ v-model="selectionAvatarValue"
452
+ label=""
453
+ :items="userItems"
454
+ :density="'comfortable'"
455
+ menu-icon="heroicons:chevron-down"
456
+ >
457
+ <template #selection="{ item }">
458
+ <span class="selection-with-avatar">
459
+ <span class="selection-avatar">{{ item.raw.initials }}</span>
460
+ <span>{{ item.raw.title }}</span>
461
+ </span>
462
+ </template>
463
+ <template #item="{ item, props: itemProps }">
464
+ <v-list-item v-bind="itemProps">
465
+ <div class="user-item-content">
466
+ <div class="user-avatar">{{ item.raw.initials }}</div>
467
+ <div class="user-info">
468
+ <span class="user-name">{{ item.raw.title }}</span>
469
+ <span class="user-email">{{ item.raw.email }}</span>
470
+ </div>
471
+ </div>
472
+ </v-list-item>
473
+ </template>
474
+ </Select>
475
+ </div>
476
+
477
+ <div class="example-item">
478
+ <h4>Selection with Country Flag</h4>
479
+ <Select
480
+ v-model="selectionFlagValue"
481
+ label="Select a country"
482
+ :items="countryItemsWithFlags"
483
+ >
484
+ <template #selection="{ item }">
485
+ <span class="selection-with-flag">
486
+ <span class="country-flag">{{ item.raw.flag }}</span>
487
+ <span>{{ item.raw.title }}</span>
488
+ </span>
489
+ </template>
490
+ <template #item="{ item, props: itemProps }">
491
+ <v-list-item v-bind="itemProps">
492
+ <template #prepend>
493
+ <span class="country-flag">{{ item.raw.flag }}</span>
494
+ </template>
495
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
496
+ </v-list-item>
497
+ </template>
498
+ </Select>
499
+ </div>
500
+
501
+ <div class="example-item wide">
502
+ <h4>Multiple Selection with Custom Chips</h4>
503
+ <Select
504
+ v-model="selectionMultipleValue"
505
+ label="Select fruits"
506
+ :items="fruitItemsWithIcons"
507
+ :multiple="true"
508
+ >
509
+ <template #selection="{ item, index }">
510
+ <v-chip
511
+ v-if="index < 3"
512
+ size="small"
513
+ class="custom-chip"
514
+ closable
515
+ @click:close="removeSelection(index)"
516
+ >
517
+ <span class="chip-icon">{{ item.raw.icon }}</span>
518
+ {{ item.raw.title }}
519
+ </v-chip>
520
+ <span v-if="index === 3" class="more-indicator">
521
+ (+{{ selectionMultipleValue.length - 3 }} more)
522
+ </span>
523
+ </template>
524
+ <template #item="{ item, props: itemProps }">
525
+ <v-list-item v-bind="itemProps">
526
+ <template #prepend>
527
+ <span class="item-icon">{{ item.raw.icon }}</span>
528
+ </template>
529
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
530
+ </v-list-item>
531
+ </template>
532
+ </Select>
533
+ </div>
534
+
535
+ <div class="example-item wide">
536
+ <h4>Multiple Selection with Color Tags</h4>
537
+ <Select
538
+ v-model="selectionColorTagsValue"
539
+ label="Select tags"
540
+ :items="colorTagItems"
541
+ :multiple="true"
542
+ >
543
+ <template #selection="{ item }">
544
+ <span
545
+ class="color-tag"
546
+ :style="{ backgroundColor: item.raw.color, color: item.raw.textColor }"
547
+ >
548
+ {{ item.raw.title }}
549
+ </span>
550
+ </template>
551
+ <template #item="{ item, props: itemProps }">
552
+ <v-list-item v-bind="itemProps">
553
+ <template #prepend>
554
+ <span
555
+ class="color-dot"
556
+ :style="{ backgroundColor: item.raw.color }"
557
+ ></span>
558
+ </template>
559
+ <v-list-item-title>{{ item.raw.title }}</v-list-item-title>
560
+ </v-list-item>
561
+ </template>
562
+ </Select>
563
+ </div>
564
+ </div>
565
+ </div>
566
+ <!-- Patient Search (Figma Design) -->
567
+ <div class="section">
568
+ <h3 class="section-title">Patient Search (Figma Design)</h3>
569
+ <p class="section-description">Autocomplete with custom item rendering, bold matching text, and empty state</p>
570
+ <div class="examples-grid">
571
+ <div class="example-item">
572
+ <h4>Patient Search</h4>
573
+ <SelectAutocomplete
574
+ v-model="patientSearchValue"
575
+ label=""
576
+ placeholder="Gebe den Patienten Namen ein"
577
+ :persistent-placeholder="true"
578
+ :items="patientSearchItems"
579
+ :clearable="true"
580
+ clear-icon="mdi-close"
581
+ :return-object="true"
582
+ item-title="name"
583
+ item-value="id"
584
+ :auto-select-first="true"
585
+ :custom-filter="patientFilter"
586
+ @update:search="onPatientSearch"
587
+ >
588
+ <template #append-inner>
589
+ <svg v-if="!patientSearchQuery" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
590
+ </template>
591
+ <template #item="{ item, props: itemProps }">
592
+ <v-list-item v-bind="itemProps" :title="undefined" class="patient-search-item">
593
+ <template #default>
594
+ <div class="patient-row">
595
+ <div class="patient-left">
596
+ <span class="patient-name" v-html="highlightMatch(item.raw.name, patientSearchQuery)"></span>
597
+ <span class="patient-id">#{{ item.raw.patientId }}</span>
598
+ </div>
599
+ <span class="patient-dob">{{ item.raw.dob }}</span>
600
+ </div>
601
+ </template>
602
+ </v-list-item>
603
+ </template>
604
+ <template #no-data>
605
+ <div class="patient-no-data">
606
+ <p class="patient-no-data-title">Kein Patient gefunden</p>
607
+ <p class="patient-no-data-desc">Bitte überprüfen Sie die Eingabe oder versuchen Sie es mit einem anderen Namen.</p>
608
+ <button class="patient-add-btn" @click="onAddPatient">Neuen Patienten hinzufügen</button>
609
+ </div>
610
+ </template>
611
+ </SelectAutocomplete>
612
+ <div v-if="patientSearchValue" class="patient-selected-display">
613
+ <div class="patient-selected-info">
614
+ <span class="patient-selected-name">{{ patientSearchValue.name }}</span>
615
+ <span class="patient-selected-meta">#{{ patientSearchValue.patientId }}, {{ patientSearchValue.dob }}</span>
616
+ </div>
617
+ <button class="patient-edit-btn" @click="patientSearchValue = null">
618
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>
619
+ </button>
620
+ </div>
621
+ </div>
622
+ </div>
623
+ </div>
624
+
625
+ <!-- SelectAutocomplete Section -->
626
+ <div class="section">
627
+ <h3 class="section-title">SelectAutocomplete</h3>
628
+ <p class="section-description">Searchable select with autocomplete filtering</p>
629
+ <div class="examples-grid">
630
+ <div class="example-item">
631
+ <h4>Default</h4>
632
+ <SelectAutocomplete
633
+ v-model="autocompleteBasicValue"
634
+ label="Search a fruit"
635
+ :items="fruitItems"
636
+ />
637
+ <p class="value-display">Selected: {{ autocompleteBasicValue?.title || 'None' }}</p>
638
+ </div>
639
+
640
+ <div class="example-item">
641
+ <h4>With Placeholder</h4>
642
+ <SelectAutocomplete
643
+ v-model="autocompletePlaceholderValue"
644
+ label="Treatment"
645
+ placeholder="Type to search..."
646
+ :persistent-placeholder="true"
647
+ :items="treatmentItems"
648
+ />
649
+ </div>
650
+
651
+ <div class="example-item">
652
+ <h4>Clearable</h4>
653
+ <SelectAutocomplete
654
+ v-model="autocompleteClearableValue"
655
+ label="Clearable Autocomplete"
656
+ :items="fruitItems"
657
+ :clearable="true"
658
+ />
659
+ </div>
660
+
661
+ <div class="example-item">
662
+ <h4>Disabled</h4>
663
+ <SelectAutocomplete
664
+ v-model="autocompleteDisabledValue"
665
+ label="Disabled Autocomplete"
666
+ :items="fruitItems"
667
+ :disabled="true"
668
+ />
669
+ </div>
670
+
671
+ <div class="example-item">
672
+ <h4>Error State</h4>
673
+ <SelectAutocomplete
674
+ v-model="autocompleteErrorValue"
675
+ label="Error Autocomplete"
676
+ :items="fruitItems"
677
+ :error="true"
678
+ />
679
+ </div>
680
+
681
+ <div class="example-item">
682
+ <h4>Country Search</h4>
683
+ <SelectAutocomplete
684
+ v-model="autocompleteCountryValue"
685
+ label="Country"
686
+ placeholder="Search country..."
687
+ :items="countryItems"
688
+ :clearable="true"
689
+ />
690
+ </div>
691
+
692
+ <div class="example-item wide">
693
+ <h4>Multiple with Chips</h4>
694
+ <SelectAutocomplete
695
+ v-model="autocompleteMultipleValue"
696
+ label="Select multiple"
697
+ :items="tagItems"
698
+ :multiple="true"
699
+ :chips="true"
700
+ :closable-chips="true"
701
+ :clearable="true"
702
+ />
703
+ <p class="value-display">Selected: {{ autocompleteMultipleValue?.map(v => v.title).join(', ') || 'None' }}</p>
704
+ </div>
705
+ </div>
706
+ </div>
707
+ </div>
708
+ </div>
709
+ </template>
710
+
711
+ <script setup lang="ts">
712
+ import { computed, ref } from "vue";
713
+ import {
714
+ domain,
715
+ setTestingDomain,
716
+ clearTestingDomain,
717
+ } from "@/utils/index";
718
+
719
+ import Select from "@/components/Select/Select.vue";
720
+ import SelectAutocomplete from "@/components/SelectAutocomplete/SelectAutocomplete.vue";
721
+ import ListItem from "@/components/ListItem/ListItem.vue";
722
+ import { avatarPlaceholder } from "..";
723
+
724
+ const currentDomain = computed(() => domain.value);
725
+
726
+ const switchToDental = () => {
727
+ setTestingDomain("domain-dental");
728
+ };
729
+
730
+ const switchToCocoon = () => {
731
+ setTestingDomain("domain-cocoon");
732
+ };
733
+
734
+ const resetDomain = () => {
735
+ clearTestingDomain();
736
+ };
737
+
738
+ // Sample items
739
+ const fruitItems = [
740
+ { title: 'Apple', value: 'apple' },
741
+ { title: 'Banana', value: 'banana' },
742
+ { title: 'Cherry', value: 'cherry' },
743
+ { title: 'Orange', value: 'orange' },
744
+ { title: 'Strawberry', value: 'strawberry' },
745
+ ];
746
+
747
+ const countryItems = [
748
+ { title: 'Deutschland', value: 'de' },
749
+ { title: 'Österreich', value: 'at' },
750
+ { title: 'Schweiz', value: 'ch' },
751
+ { title: 'Frankreich', value: 'fr' },
752
+ { title: 'Italien', value: 'it' },
753
+ ];
754
+
755
+ const treatmentItems = [
756
+ { title: 'Zahnreinigung', value: 'cleaning' },
757
+ { title: 'Kontrolluntersuchung', value: 'checkup' },
758
+ { title: 'Implantologie', value: 'implant' },
759
+ { title: 'Kieferorthopädie', value: 'ortho' },
760
+ { title: 'Wurzelbehandlung', value: 'root' },
761
+ ];
762
+
763
+ const tagItems = [
764
+ { title: 'Urgent', value: 'urgent' },
765
+ { title: 'Follow-up', value: 'followup' },
766
+ { title: 'New Patient', value: 'new' },
767
+ { title: 'VIP', value: 'vip' },
768
+ { title: 'Insurance Pending', value: 'insurance' },
769
+ ];
770
+
771
+ // Patient search items (Figma design)
772
+ const patientSearchItems = [
773
+ { name: 'Weber, Wolfgang', patientId: '06432', dob: '12.09.2001', id: '1' },
774
+ { name: 'Krause, Wolfram', patientId: '26152', dob: '12.04.1954', id: '2' },
775
+ { name: 'Wolff, Wolfhard', patientId: '82692', dob: '15.05.1953', id: '3' },
776
+ { name: 'Adler, Wolfbert', patientId: '83827', dob: '12.09.2000', id: '4' },
777
+ { name: 'Schulz, Wolfgang', patientId: '72376', dob: '05.12.1987', id: '5' },
778
+ ];
779
+
780
+ // Custom item slot examples
781
+ const fruitItemsWithIcons = [
782
+ { title: 'Apple', value: 'apple', icon: '🍎' },
783
+ { title: 'Banana', value: 'banana', icon: '🍌' },
784
+ { title: 'Cherry', value: 'cherry', icon: '🍒' },
785
+ { title: 'Orange', value: 'orange', icon: '🍊' },
786
+ { title: 'Strawberry', value: 'strawberry', icon: '🍓' },
787
+ ];
788
+
789
+ const treatmentItemsWithDesc = [
790
+ { title: 'Zahnreinigung', value: 'cleaning', description: 'Professionelle Reinigung und Politur' },
791
+ { title: 'Kontrolluntersuchung', value: 'checkup', description: 'Regelmäßige Kontrolle der Zahngesundheit' },
792
+ { title: 'Implantologie', value: 'implant', description: 'Ersatz fehlender Zähne durch Implantate' },
793
+ { title: 'Wurzelbehandlung', value: 'root', description: 'Behandlung des Zahnmarks' },
794
+ ];
795
+
796
+ const patientItems = [
797
+ { title: 'Max Mustermann', value: 'max', status: 'active', statusLabel: 'Aktiv' },
798
+ { title: 'Anna Schmidt', value: 'anna', status: 'waiting', statusLabel: 'Wartend' },
799
+ { title: 'Peter Weber', value: 'peter', status: 'inactive', statusLabel: 'Inaktiv' },
800
+ { title: 'Lisa Müller', value: 'lisa', status: 'active', statusLabel: 'Aktiv' },
801
+ ];
802
+
803
+ const userItems = [
804
+ { title: 'Dr. Maria Schmidt', value: 'maria', initials: 'MS', email: 'maria@praxis.de' },
805
+ { title: 'Dr. Thomas Bauer', value: 'thomas', initials: 'TB', email: 'thomas@praxis.de' },
806
+ { title: 'Julia Fischer', value: 'julia', initials: 'JF', email: 'julia@praxis.de' },
807
+ ];
808
+
809
+ // Custom selection slot examples
810
+ const countryItemsWithFlags = [
811
+ { title: 'Deutschland', value: 'de', flag: '🇩🇪' },
812
+ { title: 'Österreich', value: 'at', flag: '🇦🇹' },
813
+ { title: 'Schweiz', value: 'ch', flag: '🇨🇭' },
814
+ { title: 'Frankreich', value: 'fr', flag: '🇫🇷' },
815
+ { title: 'Italien', value: 'it', flag: '🇮🇹' },
816
+ ];
817
+
818
+ const colorTagItems = [
819
+ { title: 'High Priority', value: 'high', color: '#ef4444', textColor: '#ffffff' },
820
+ { title: 'Medium Priority', value: 'medium', color: '#f59e0b', textColor: '#ffffff' },
821
+ { title: 'Low Priority', value: 'low', color: '#22c55e', textColor: '#ffffff' },
822
+ { title: 'On Hold', value: 'hold', color: '#6b7280', textColor: '#ffffff' },
823
+ { title: 'In Progress', value: 'progress', color: '#3b82f6', textColor: '#ffffff' },
824
+ ];
825
+
826
+ // Basic examples
827
+ const basicValue = ref(null);
828
+ const placeholderValue = ref(null);
829
+ const clearableValue = ref(null);
830
+ const borderHoverValue = ref(null);
831
+
832
+ // States
833
+ const normalState = ref(null);
834
+ const disabledValue = ref({ title: 'Apple', value: 'apple' });
835
+ const errorValue = ref(null);
836
+ const preselectedValue = ref({ title: 'Cherry', value: 'cherry' });
837
+
838
+ // Multiple selection
839
+ const multipleValue = ref([]);
840
+ const chipsValue = ref([]);
841
+ const closableChipsValue = ref([
842
+ { title: 'Apple', value: 'apple' },
843
+ { title: 'Cherry', value: 'cherry' },
844
+ ]);
845
+
846
+ // Variants
847
+ const variantOutlined = ref(null);
848
+ const variantUnderlined = ref(null);
849
+ const variantFilled = ref(null);
850
+ const variantSolo = ref(null);
851
+ const variantSoloFilled = ref(null);
852
+ const variantPlain = ref(null);
853
+
854
+ // Density
855
+ const densityDefault = ref(null);
856
+ const densityComfortable = ref(null);
857
+ const densityDefaultSize = ref(null);
858
+
859
+ // Practical examples
860
+ const countryValue = ref(null);
861
+ const treatmentValue = ref(null);
862
+ const tagsValue = ref([]);
863
+
864
+ // Patient search (Figma design)
865
+ const patientSearchValue = ref(null);
866
+ const patientSearchQuery = ref('');
867
+
868
+ const patientFilter = (_value: string, query: string, item: any) => {
869
+ if (!query) return true;
870
+ const q = query.toLowerCase();
871
+ const raw = item.raw;
872
+ return (
873
+ raw.name?.toLowerCase().includes(q) ||
874
+ raw.patientId?.toLowerCase().includes(q) ||
875
+ raw.dob?.toLowerCase().includes(q)
876
+ );
877
+ };
878
+
879
+ const onPatientSearch = (val: string) => {
880
+ patientSearchQuery.value = val || '';
881
+ };
882
+
883
+ const highlightMatch = (text: string, query: string): string => {
884
+ if (!query) return text;
885
+ const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
886
+ const regex = new RegExp(`(${escaped})`, 'gi');
887
+ return text.replace(regex, '<strong>$1</strong>');
888
+ };
889
+
890
+ const onAddPatient = () => {
891
+ alert('Neuen Patienten hinzufügen');
892
+ };
893
+
894
+ // Custom item slot examples
895
+ const customItemValue = ref(null);
896
+ const customItemDescValue = ref(null);
897
+ const customItemStatusValue = ref(null);
898
+ const customLayoutValue = ref(null);
899
+
900
+ // Custom selection slot examples
901
+ const selectionIconValue = ref(null);
902
+ const selectionStatusValue = ref(null);
903
+ const selectionAvatarValue = ref(null);
904
+ const selectionFlagValue = ref(null);
905
+ const selectionMultipleValue = ref([]);
906
+ const selectionColorTagsValue = ref([]);
907
+
908
+ const removeSelection = (index: number) => {
909
+ selectionMultipleValue.value.splice(index, 1);
910
+ };
911
+ </script>
912
+
913
+ <style scoped>
914
+ .page {
915
+ display: flex;
916
+ flex-direction: column;
917
+ justify-content: flex-start;
918
+ align-items: center;
919
+ width: 100vw;
920
+ min-height: 100vh;
921
+ background-color: #f5f5f5;
922
+ padding: 2rem 0;
923
+ overflow-y: auto;
924
+ }
925
+
926
+ .element-container {
927
+ display: flex;
928
+ flex-direction: column;
929
+ justify-content: flex-start;
930
+ align-items: center;
931
+ width: 95%;
932
+ max-width: 1400px;
933
+ gap: 2rem;
934
+ }
935
+
936
+ .controls {
937
+ width: 100%;
938
+ background: white;
939
+ padding: 1.5rem;
940
+ border-radius: 8px;
941
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
942
+ text-align: center;
943
+ }
944
+
945
+ .controls h2 {
946
+ margin: 0 0 1rem 0;
947
+ color: #333;
948
+ font-size: 1.5rem;
949
+ }
950
+
951
+ .button-group {
952
+ display: flex;
953
+ gap: 1rem;
954
+ justify-content: center;
955
+ flex-wrap: wrap;
956
+ }
957
+
958
+ .control-btn {
959
+ padding: 0.75rem 1.5rem;
960
+ font-size: 1rem;
961
+ border: none;
962
+ border-radius: 6px;
963
+ cursor: pointer;
964
+ background-color: #4caf50;
965
+ color: white;
966
+ transition: background-color 0.3s ease;
967
+ font-weight: 500;
968
+ }
969
+
970
+ .control-btn:hover {
971
+ background-color: #45a049;
972
+ }
973
+
974
+ .control-btn.reset {
975
+ background-color: #f44336;
976
+ }
977
+
978
+ .control-btn.reset:hover {
979
+ background-color: #da190b;
980
+ }
981
+
982
+ .section {
983
+ width: 100%;
984
+ background: white;
985
+ padding: 1.5rem;
986
+ border-radius: 8px;
987
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
988
+ }
989
+
990
+ .section-title {
991
+ margin: 0 0 1.5rem 0;
992
+ color: #333;
993
+ font-size: 1.25rem;
994
+ font-weight: 600;
995
+ border-bottom: 2px solid #e0e0e0;
996
+ padding-bottom: 0.5rem;
997
+ }
998
+
999
+ .examples-grid {
1000
+ display: grid;
1001
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
1002
+ gap: 1.5rem;
1003
+ }
1004
+
1005
+ .example-item {
1006
+ display: flex;
1007
+ flex-direction: column;
1008
+ gap: 0.5rem;
1009
+ }
1010
+
1011
+ .example-item.wide {
1012
+ grid-column: span 2;
1013
+ }
1014
+
1015
+ .example-item h4 {
1016
+ margin: 0;
1017
+ font-size: 0.875rem;
1018
+ font-weight: 600;
1019
+ color: #555;
1020
+ }
1021
+
1022
+ .value-display {
1023
+ margin: 0.5rem 0 0 0;
1024
+ font-size: 0.8125rem;
1025
+ color: #666;
1026
+ font-style: italic;
1027
+ }
1028
+
1029
+ @media (max-width: 768px) {
1030
+ .examples-grid {
1031
+ grid-template-columns: 1fr;
1032
+ }
1033
+
1034
+ .example-item.wide {
1035
+ grid-column: span 1;
1036
+ }
1037
+ }
1038
+
1039
+ /* Custom item slot styles */
1040
+ .item-icon {
1041
+ font-size: 1.25rem;
1042
+ margin-right: 0.5rem;
1043
+ }
1044
+
1045
+ .status-dot {
1046
+ width: 10px;
1047
+ height: 10px;
1048
+ border-radius: 50%;
1049
+ margin-right: 0.5rem;
1050
+ }
1051
+
1052
+ .status-dot.active {
1053
+ background-color: #4caf50;
1054
+ }
1055
+
1056
+ .status-dot.waiting {
1057
+ background-color: #ff9800;
1058
+ }
1059
+
1060
+ .status-dot.inactive {
1061
+ background-color: #9e9e9e;
1062
+ }
1063
+
1064
+ .status-badge {
1065
+ font-size: 0.75rem;
1066
+ padding: 0.125rem 0.5rem;
1067
+ border-radius: 999px;
1068
+ font-weight: 500;
1069
+ }
1070
+
1071
+ .status-badge.active {
1072
+ background-color: #e8f5e9;
1073
+ color: #2e7d32;
1074
+ }
1075
+
1076
+ .status-badge.waiting {
1077
+ background-color: #fff3e0;
1078
+ color: #ef6c00;
1079
+ }
1080
+
1081
+ .status-badge.inactive {
1082
+ background-color: #f5f5f5;
1083
+ color: #757575;
1084
+ }
1085
+
1086
+ .user-item-content {
1087
+ display: flex;
1088
+ align-items: center;
1089
+ gap: 0.75rem;
1090
+ padding: 0.25rem 0;
1091
+ }
1092
+
1093
+ .user-avatar {
1094
+ width: 36px;
1095
+ height: 36px;
1096
+ border-radius: 50%;
1097
+ background-color: #172774;
1098
+ color: white;
1099
+ display: flex;
1100
+ align-items: center;
1101
+ justify-content: center;
1102
+ font-size: 0.875rem;
1103
+ font-weight: 600;
1104
+ }
1105
+
1106
+ .user-info {
1107
+ display: flex;
1108
+ flex-direction: column;
1109
+ }
1110
+
1111
+ .user-name {
1112
+ font-weight: 500;
1113
+ color: #333;
1114
+ }
1115
+
1116
+ .user-email {
1117
+ font-size: 0.75rem;
1118
+ color: #666;
1119
+ }
1120
+
1121
+ /* Section description */
1122
+ .section-description {
1123
+ margin: -1rem 0 1.5rem 0;
1124
+ font-size: 0.875rem;
1125
+ color: #666;
1126
+ }
1127
+
1128
+ /* Custom selection slot styles */
1129
+ .selection-with-icon,
1130
+ .selection-with-status,
1131
+ .selection-with-avatar,
1132
+ .selection-with-flag {
1133
+ display: inline-flex;
1134
+ align-items: center;
1135
+ gap: 0.5rem;
1136
+ }
1137
+
1138
+ .selection-icon {
1139
+ font-size: 1.125rem;
1140
+ }
1141
+
1142
+ .selection-avatar {
1143
+ width: 24px;
1144
+ height: 24px;
1145
+ border-radius: 50%;
1146
+ background-color: #172774;
1147
+ color: white;
1148
+ display: inline-flex;
1149
+ align-items: center;
1150
+ justify-content: center;
1151
+ font-size: 0.625rem;
1152
+ font-weight: 600;
1153
+ }
1154
+
1155
+ .country-flag {
1156
+ font-size: 1.25rem;
1157
+ margin-right: 0.25rem;
1158
+ }
1159
+
1160
+ .custom-chip {
1161
+ margin: 2px;
1162
+ }
1163
+
1164
+ .chip-icon {
1165
+ margin-right: 0.25rem;
1166
+ }
1167
+
1168
+ .more-indicator {
1169
+ font-size: 0.75rem;
1170
+ color: #666;
1171
+ margin-left: 0.25rem;
1172
+ }
1173
+
1174
+ .color-tag {
1175
+ display: inline-block;
1176
+ padding: 0.125rem 0.5rem;
1177
+ border-radius: 4px;
1178
+ font-size: 0.75rem;
1179
+ font-weight: 500;
1180
+ margin: 2px;
1181
+ }
1182
+
1183
+ .color-dot {
1184
+ width: 12px;
1185
+ height: 12px;
1186
+ border-radius: 50%;
1187
+ margin-right: 0.5rem;
1188
+ }
1189
+
1190
+ /* Patient Search (Figma Design) styles */
1191
+ .patient-row {
1192
+ display: flex;
1193
+ justify-content: space-between;
1194
+ align-items: flex-start;
1195
+ width: 100%;
1196
+ padding: 0.375rem 0;
1197
+ }
1198
+
1199
+ .patient-left {
1200
+ display: flex;
1201
+ flex-direction: column;
1202
+ gap: 0.125rem;
1203
+ }
1204
+
1205
+ .patient-name {
1206
+ font-size: 0.9375rem;
1207
+ font-weight: 400;
1208
+ color: var(--Dental-Blue-0, #172774);
1209
+ }
1210
+
1211
+ .patient-id {
1212
+ font-size: 0.75rem;
1213
+ color: var(--Soft-Concrete-2, #9e9e9e);
1214
+ }
1215
+
1216
+ .patient-dob {
1217
+ font-size: 0.875rem;
1218
+ color: var(--Dental-Blue-0, #172774);
1219
+ white-space: nowrap;
1220
+ margin-left: 1rem;
1221
+ }
1222
+
1223
+ .patient-no-data {
1224
+ display: flex;
1225
+ flex-direction: column;
1226
+ align-items: center;
1227
+ padding: 1.5rem 1rem;
1228
+ text-align: center;
1229
+ }
1230
+
1231
+ .patient-no-data-title {
1232
+ font-size: 0.9375rem;
1233
+ font-weight: 600;
1234
+ color: var(--Dental-Blue-0, #172774);
1235
+ margin: 0 0 0.5rem 0;
1236
+ }
1237
+
1238
+ .patient-no-data-desc {
1239
+ font-size: 0.8125rem;
1240
+ color: var(--Soft-Concrete-2, #9e9e9e);
1241
+ margin: 0 0 1rem 0;
1242
+ max-width: 260px;
1243
+ line-height: 1.4;
1244
+ }
1245
+
1246
+ .patient-add-btn {
1247
+ background: none;
1248
+ border: 1.5px solid var(--Dental-Blue-0, #172774);
1249
+ color: var(--Dental-Blue-0, #172774);
1250
+ border-radius: 999px;
1251
+ padding: 0.5rem 1.25rem;
1252
+ font-size: 0.875rem;
1253
+ font-weight: 500;
1254
+ cursor: pointer;
1255
+ transition: background-color 0.2s;
1256
+ }
1257
+
1258
+ .patient-add-btn:hover {
1259
+ background-color: rgba(23, 39, 116, 0.05);
1260
+ }
1261
+
1262
+ .patient-selected-display {
1263
+ display: flex;
1264
+ justify-content: space-between;
1265
+ align-items: center;
1266
+ margin-top: 0.75rem;
1267
+ padding: 0 0.25rem;
1268
+ }
1269
+
1270
+ .patient-selected-info {
1271
+ display: flex;
1272
+ flex-direction: column;
1273
+ gap: 0.125rem;
1274
+ }
1275
+
1276
+ .patient-selected-name {
1277
+ font-size: 0.9375rem;
1278
+ font-weight: 500;
1279
+ color: var(--Dental-Blue-0, #172774);
1280
+ }
1281
+
1282
+ .patient-selected-meta {
1283
+ font-size: 0.75rem;
1284
+ color: var(--Soft-Concrete-2, #9e9e9e);
1285
+ }
1286
+
1287
+ .patient-edit-btn {
1288
+ background: none;
1289
+ border: none;
1290
+ cursor: pointer;
1291
+ color: var(--Dental-Blue-0, #172774);
1292
+ padding: 0.25rem;
1293
+ border-radius: 4px;
1294
+ display: flex;
1295
+ align-items: center;
1296
+ justify-content: center;
1297
+ }
1298
+
1299
+ .patient-edit-btn:hover {
1300
+ background-color: rgba(23, 39, 116, 0.05);
1301
+ }
1302
+ </style>