origam 2.12.1 → 2.13.0

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 (128) hide show
  1. package/dist/src/assets/locales/en.json +114 -76
  2. package/dist/src/assets/locales/fr.json +117 -74
  3. package/dist/src/components/BottomNav/OrigamBottomNav.vue +6 -4
  4. package/dist/src/components/Breadcrumb/OrigamBreadcrumb.vue +1 -1
  5. package/dist/src/components/Breadcrumb/OrigamBreadcrumbDivider.vue +1 -1
  6. package/dist/src/components/Breadcrumb/OrigamBreadcrumbItem.vue +2 -2
  7. package/dist/src/components/Btn/OrigamBtn.vue +1 -1
  8. package/dist/src/components/Calendar/OrigamCalendar.vue +3 -3
  9. package/dist/src/components/Carousel/OrigamCarousel.vue +1 -1
  10. package/dist/src/components/Clipboard/OrigamClipboard.vue +1 -1
  11. package/dist/src/components/Code/OrigamCode.vue +1 -1
  12. package/dist/src/components/ColorPicker/OrigamColorPickerCanvas.vue +2 -2
  13. package/dist/src/components/ContextualMenu/OrigamContextualMenu.vue +1 -0
  14. package/dist/src/components/DataTable/OrigamDataTableFooter.vue +8 -8
  15. package/dist/src/components/DataTable/OrigamDataTableHeadersCellMobile.vue +1 -1
  16. package/dist/src/components/DataTable/OrigamDataTableRow.vue +1 -1
  17. package/dist/src/components/DataTable/OrigamDataTableRows.vue +2 -2
  18. package/dist/src/components/DatePicker/OrigamDatePicker.vue +3 -3
  19. package/dist/src/components/DatePickerField/OrigamDatePickerField.vue +1 -1
  20. package/dist/src/components/ExpansionPanel/OrigamExpansionPanelHeader.vue +8 -3
  21. package/dist/src/components/FileField/OrigamFileField.vue +8 -8
  22. package/dist/src/components/InfiniteScroll/OrigamInfiniteScroll.vue +2 -2
  23. package/dist/src/components/List/OrigamList.vue +7 -0
  24. package/dist/src/components/List/OrigamListItem.vue +71 -3
  25. package/dist/src/components/Media/OrigamMediaController.vue +9 -9
  26. package/dist/src/components/Menu/OrigamMenu.vue +6 -1
  27. package/dist/src/components/Pagination/OrigamPagination.vue +8 -8
  28. package/dist/src/components/RatingField/OrigamRatingFieldItem.vue +1 -1
  29. package/dist/src/components/Select/OrigamSelect.vue +7 -2
  30. package/dist/src/components/SelectionControl/OrigamSelectionControl.vue +6 -3
  31. package/dist/src/components/SelectionControl/OrigamSelectionControlGroup.vue +15 -0
  32. package/dist/src/components/Stepper/OrigamStepper.vue +1 -1
  33. package/dist/src/components/Stepper/OrigamStepperItem.vue +1 -1
  34. package/dist/src/components/Switch/OrigamSwitch.vue +453 -449
  35. package/dist/src/components/TextField/OrigamTextField.vue +4 -1
  36. package/dist/src/components/TextareaField/OrigamRichToolbar.vue +8 -8
  37. package/dist/src/components/TextareaField/OrigamTextareaField.vue +1 -1
  38. package/dist/src/components/Title/OrigamTitle.vue +6 -4
  39. package/dist/src/components/Video/OrigamVideo.vue +3 -3
  40. package/dist/src/composables/Commons/group.composable.cjs +2 -2
  41. package/dist/src/composables/Commons/group.composable.js +2 -2
  42. package/dist/src/composables/Commons/style.composable.cjs +14 -12
  43. package/dist/src/composables/Commons/style.composable.d.ts +16 -2
  44. package/dist/src/composables/Commons/style.composable.js +16 -14
  45. package/dist/src/consts/Btn/btn-toggle.const.cjs +1 -1
  46. package/dist/src/consts/Btn/btn-toggle.const.js +1 -1
  47. package/dist/src/consts/Chip/chip-group.const.cjs +1 -1
  48. package/dist/src/consts/Chip/chip-group.const.js +1 -1
  49. package/dist/src/consts/Commons/date.const.cjs +2 -2
  50. package/dist/src/consts/Commons/date.const.js +2 -2
  51. package/dist/src/consts/Commons/defaults.const.cjs +1 -1
  52. package/dist/src/consts/Commons/defaults.const.js +1 -1
  53. package/dist/src/consts/Commons/display.const.cjs +1 -1
  54. package/dist/src/consts/Commons/display.const.js +1 -1
  55. package/dist/src/consts/Commons/forwardRefs.const.cjs +1 -1
  56. package/dist/src/consts/Commons/forwardRefs.const.js +1 -1
  57. package/dist/src/consts/Commons/goTo.const.cjs +1 -1
  58. package/dist/src/consts/Commons/goTo.const.js +1 -1
  59. package/dist/src/consts/Commons/hover.const.cjs +1 -1
  60. package/dist/src/consts/Commons/hover.const.js +1 -1
  61. package/dist/src/consts/Commons/layout.const.cjs +2 -2
  62. package/dist/src/consts/Commons/layout.const.js +2 -2
  63. package/dist/src/consts/Commons/locale.const.cjs +1 -1
  64. package/dist/src/consts/Commons/locale.const.js +1 -1
  65. package/dist/src/consts/Commons/nested.const.cjs +1 -1
  66. package/dist/src/consts/Commons/nested.const.js +1 -1
  67. package/dist/src/consts/Commons/ripple.const.cjs +1 -1
  68. package/dist/src/consts/Commons/ripple.const.js +1 -1
  69. package/dist/src/consts/Commons/stack.const.cjs +1 -1
  70. package/dist/src/consts/Commons/stack.const.js +1 -1
  71. package/dist/src/consts/DataTable/expand.const.cjs +1 -1
  72. package/dist/src/consts/DataTable/expand.const.js +1 -1
  73. package/dist/src/consts/DataTable/group.const.cjs +1 -1
  74. package/dist/src/consts/DataTable/group.const.js +1 -1
  75. package/dist/src/consts/DataTable/headers.const.cjs +1 -1
  76. package/dist/src/consts/DataTable/headers.const.js +1 -1
  77. package/dist/src/consts/DataTable/pagination.const.cjs +1 -1
  78. package/dist/src/consts/DataTable/pagination.const.js +1 -1
  79. package/dist/src/consts/DataTable/select.const.cjs +2 -2
  80. package/dist/src/consts/DataTable/select.const.js +2 -2
  81. package/dist/src/consts/DataTable/sort.const.cjs +1 -1
  82. package/dist/src/consts/DataTable/sort.const.js +1 -1
  83. package/dist/src/consts/ExpansionPanel/expansion-panel.const.cjs +1 -1
  84. package/dist/src/consts/ExpansionPanel/expansion-panel.const.js +1 -1
  85. package/dist/src/consts/Form/form.const.cjs +1 -1
  86. package/dist/src/consts/Form/form.const.js +1 -1
  87. package/dist/src/consts/Icon/icon.const.cjs +1 -1
  88. package/dist/src/consts/Icon/icon.const.js +1 -1
  89. package/dist/src/consts/ItemGroup/item-group.const.cjs +1 -1
  90. package/dist/src/consts/ItemGroup/item-group.const.js +1 -1
  91. package/dist/src/consts/List/list.const.cjs +1 -1
  92. package/dist/src/consts/List/list.const.js +1 -1
  93. package/dist/src/consts/Menu/menu.const.cjs +1 -1
  94. package/dist/src/consts/Menu/menu.const.js +1 -1
  95. package/dist/src/consts/Parallax/parallax-container.const.cjs +1 -1
  96. package/dist/src/consts/Parallax/parallax-container.const.js +1 -1
  97. package/dist/src/consts/Parallax/parallax-layer.const.cjs +1 -1
  98. package/dist/src/consts/Parallax/parallax-layer.const.js +1 -1
  99. package/dist/src/consts/SelectionControl/selection-control.const.cjs +1 -1
  100. package/dist/src/consts/SelectionControl/selection-control.const.js +1 -1
  101. package/dist/src/consts/Slide/slide-group.const.cjs +1 -1
  102. package/dist/src/consts/Slide/slide-group.const.js +1 -1
  103. package/dist/src/consts/Stepper/stepper.const.cjs +1 -1
  104. package/dist/src/consts/Stepper/stepper.const.js +1 -1
  105. package/dist/src/consts/Tabs/tabs.const.cjs +3 -3
  106. package/dist/src/consts/Tabs/tabs.const.js +3 -3
  107. package/dist/src/consts/Theme/theme.const.cjs +2 -2
  108. package/dist/src/consts/Theme/theme.const.js +2 -2
  109. package/dist/src/consts/Timeline/timeline.const.cjs +1 -1
  110. package/dist/src/consts/Timeline/timeline.const.js +1 -1
  111. package/dist/src/consts/Treeview/treeview.const.cjs +1 -1
  112. package/dist/src/consts/Treeview/treeview.const.js +1 -1
  113. package/dist/src/consts/Window/window.const.cjs +2 -2
  114. package/dist/src/consts/Window/window.const.js +2 -2
  115. package/dist/src/interfaces/Commons/commons.interface.d.ts +18 -0
  116. package/dist/src/interfaces/List/list-item.interface.d.ts +15 -2
  117. package/dist/src/interfaces/List/list.interface.d.ts +10 -2
  118. package/dist/src/interfaces/Pagination/pagination.interface.d.ts +2 -2
  119. package/dist/src/nuxt/module.cjs +3 -2
  120. package/dist/src/nuxt/module.js +2 -1
  121. package/dist/src/origam.cjs +3 -2
  122. package/dist/src/origam.js +3 -2
  123. package/dist/src/services/Commons/circular-buffer.service.cjs +1 -0
  124. package/dist/src/services/Commons/circular-buffer.service.js +1 -0
  125. package/dist/src/utils/Commons/dom.util.cjs +32 -0
  126. package/dist/src/utils/Commons/dom.util.d.ts +1 -0
  127. package/dist/src/utils/Commons/dom.util.js +31 -0
  128. package/package.json +10 -5
@@ -1,137 +1,137 @@
1
1
  <template>
2
- <div
3
- v-if="isSkeletonLoading"
4
- class="origam-switch__skeleton"
5
- :class="{ 'origam-switch__skeleton--inset': inset }"
6
- aria-busy="true"
7
- aria-label="Loading"
8
- role="status"
9
- data-cy="origam-switch-skeleton"
10
- >
11
- <span class="origam-switch__skeleton-track"/>
12
- <span class="origam-switch__skeleton-thumb"/>
13
- </div>
14
-
15
- <origam-input
16
- v-else
17
- :id="id"
18
- ref="origamInputRef"
19
- v-model="model"
20
- :class="switchClasses"
21
- :focused="isFocused"
22
- :style="switchStyles"
23
- v-bind="{ ...rootAttrs, ...inputProps }"
24
- >
25
- <template #default="{id, messagesId, isDisabled, isReadonly, isValid}">
26
- <origam-selection-control
27
- :id="id"
28
- ref="origamSelectionControlRef"
29
- v-model="model"
30
- :aria-checked="indeterminate ? 'mixed' : undefined"
31
- :aria-describedby="messagesId"
32
- :disabled="isDisabled"
33
- :readonly="isReadonly"
34
- type="checkbox"
35
- v-bind="{ ...controlProps, ...controlAttrs }"
36
- @blur="handleBlur"
37
- @focus="handleFocus"
38
- @update:model-value="handleChange"
39
- >
40
- <template #default="{bgColor: scBgColor}">
41
- <origam-switch-track
42
- ref="origamSwitchTrackRef"
43
- :bg-color="scBgColor"
44
- :disabled="isDisabled"
45
- :error="isValid === false"
46
- :inset="inset"
47
- :is-valid="isValid"
48
- :model-value="model"
49
- :readonly="isReadonly"
50
- v-bind="{ ...trackProps }"
51
- @click="handleTrackClick"
52
- >
53
- <template
54
- v-if="slots['track.true']"
55
- #track.true="slotProps"
56
- >
57
- <slot
58
- name="track.true"
59
- v-bind="slotProps"
60
- />
61
- </template>
62
-
63
- <template
64
- v-if="slots['track.false']"
65
- #track.false="slotProps"
66
- >
67
- <slot
68
- name="track.false"
69
- v-bind="slotProps"
70
- />
71
- </template>
72
-
73
- <template
74
- v-if="isLineLoading"
75
- #overlay
76
- >
77
- <origam-progress
78
- :active="loaderConfig.isActive"
79
- :color="color"
80
- :indeterminate="loaderConfig.indeterminate"
81
- :model-value="loaderConfig.modelValue"
82
- :type="PROGRESS_TYPE.LINEAR"
83
- class="origam-switch__progress origam-switch__progress--linear"
84
- data-cy="origam-switch-progress-linear"
85
- v-bind="loaderConfig.overrides"
86
- />
87
- </template>
88
- </origam-switch-track>
89
- </template>
90
-
91
- <template #input="{model, icon, props: selectionControlProps}">
92
- <input
93
- ref="input"
94
- :aria-checked="selectionControlProps.type === 'checkbox' ? model : undefined"
95
- :aria-disabled="selectionControlProps.disabled"
96
- :aria-label="selectionControlProps.label"
97
- :checked="model"
98
- v-bind="selectionControlProps"
99
- />
100
- <div
101
- :class="getSwitchThumbClasses(icon)"
102
- :style="switchThumbStyles"
103
- >
104
- <origam-translate-scale>
105
- <div
106
- v-if="hasCircularLoading"
107
- class="origam-switch__loader"
108
- >
109
- <slot name="loader">
110
- <origam-progress
111
- :active="loaderConfig.isActive"
112
- :color="color"
113
- :indeterminate="loaderConfig.indeterminate"
114
- :model-value="loaderConfig.modelValue"
115
- :size="SIZES.X_SMALL"
116
- :type="PROGRESS_TYPE.CIRCULAR"
117
- class="origam-switch__progress origam-switch__progress--circular"
118
- thickness="2"
119
- v-bind="loaderConfig.overrides"
120
- />
121
- </slot>
122
- </div>
123
-
124
- <origam-icon
125
- v-else-if="icon"
126
- :icon="icon"
127
- size="x-small"
128
- />
129
- </origam-translate-scale>
130
- </div>
131
- </template>
132
- </origam-selection-control>
133
- </template>
134
- </origam-input>
2
+ <div
3
+ v-if="isSkeletonLoading"
4
+ class="origam-switch__skeleton"
5
+ :class="{ 'origam-switch__skeleton--inset': inset }"
6
+ aria-busy="true"
7
+ aria-label="Loading"
8
+ role="status"
9
+ data-cy="origam-switch-skeleton"
10
+ >
11
+ <span class="origam-switch__skeleton-track"/>
12
+ <span class="origam-switch__skeleton-thumb"/>
13
+ </div>
14
+
15
+ <origam-input
16
+ v-else
17
+ :id="id"
18
+ ref="origamInputRef"
19
+ v-model="model"
20
+ :class="switchClasses"
21
+ :focused="isFocused"
22
+ :style="switchStyles"
23
+ v-bind="{ ...rootAttrs, ...inputProps }"
24
+ >
25
+ <template #default="{id, messagesId, isDisabled, isReadonly, isValid}">
26
+ <origam-selection-control
27
+ :id="id"
28
+ ref="origamSelectionControlRef"
29
+ v-model="model"
30
+ :aria-checked="indeterminate ? 'mixed' : undefined"
31
+ :aria-describedby="messagesId"
32
+ :disabled="isDisabled"
33
+ :readonly="isReadonly"
34
+ type="checkbox"
35
+ v-bind="{ ...controlProps, ...controlAttrs }"
36
+ @blur="handleBlur"
37
+ @focus="handleFocus"
38
+ @update:model-value="handleChange"
39
+ >
40
+ <template #default="{bgColor: scBgColor}">
41
+ <origam-switch-track
42
+ ref="origamSwitchTrackRef"
43
+ :bg-color="scBgColor"
44
+ :disabled="isDisabled"
45
+ :error="isValid === false"
46
+ :inset="inset"
47
+ :is-valid="isValid"
48
+ :model-value="model"
49
+ :readonly="isReadonly"
50
+ v-bind="{ ...trackProps }"
51
+ @click="handleTrackClick"
52
+ >
53
+ <template
54
+ v-if="slots['track.true']"
55
+ #track.true="slotProps"
56
+ >
57
+ <slot
58
+ name="track.true"
59
+ v-bind="slotProps"
60
+ />
61
+ </template>
62
+
63
+ <template
64
+ v-if="slots['track.false']"
65
+ #track.false="slotProps"
66
+ >
67
+ <slot
68
+ name="track.false"
69
+ v-bind="slotProps"
70
+ />
71
+ </template>
72
+
73
+ <template
74
+ v-if="isLineLoading"
75
+ #overlay
76
+ >
77
+ <origam-progress
78
+ :active="loaderConfig.isActive"
79
+ :color="color"
80
+ :indeterminate="loaderConfig.indeterminate"
81
+ :model-value="loaderConfig.modelValue"
82
+ :type="PROGRESS_TYPE.LINEAR"
83
+ class="origam-switch__progress origam-switch__progress--linear"
84
+ data-cy="origam-switch-progress-linear"
85
+ v-bind="loaderConfig.overrides"
86
+ />
87
+ </template>
88
+ </origam-switch-track>
89
+ </template>
90
+
91
+ <template #input="{model, icon, props: selectionControlProps}">
92
+ <input
93
+ ref="input"
94
+ :aria-checked="selectionControlProps.type === 'checkbox' ? model : undefined"
95
+ :aria-disabled="selectionControlProps.disabled"
96
+ :aria-label="selectionControlProps.label"
97
+ :checked="model"
98
+ v-bind="selectionControlProps"
99
+ />
100
+ <div
101
+ :class="getSwitchThumbClasses(icon)"
102
+ :style="switchThumbStyles"
103
+ >
104
+ <origam-translate-scale>
105
+ <div
106
+ v-if="hasCircularLoading"
107
+ class="origam-switch__loader"
108
+ >
109
+ <slot name="loader">
110
+ <origam-progress
111
+ :active="loaderConfig.isActive"
112
+ :color="color"
113
+ :indeterminate="loaderConfig.indeterminate"
114
+ :model-value="loaderConfig.modelValue"
115
+ :size="SIZES.X_SMALL"
116
+ :type="PROGRESS_TYPE.CIRCULAR"
117
+ class="origam-switch__progress origam-switch__progress--circular"
118
+ thickness="2"
119
+ v-bind="loaderConfig.overrides"
120
+ />
121
+ </slot>
122
+ </div>
123
+
124
+ <origam-icon
125
+ v-else-if="icon"
126
+ :icon="icon"
127
+ size="x-small"
128
+ />
129
+ </origam-translate-scale>
130
+ </div>
131
+ </template>
132
+ </origam-selection-control>
133
+ </template>
134
+ </origam-input>
135
135
  </template>
136
136
 
137
137
  <script lang="ts" setup>
@@ -345,320 +345,324 @@ defineExpose({
345
345
  </script>
346
346
 
347
347
  <style lang="scss" scoped>
348
- /*
349
- * Skeleton placeholder mimicking the switch silhouette — a 52×32
350
- * rounded track + a 20px circular thumb pinned to the left so the
351
- * shape is unmistakably a switch (vs the previous plain rectangle
352
- * which looked like a generic loading bar). Both halves share the
353
- * `--origam-switch__skeleton-bg` pulse animation inherited from
354
- * the broader skeleton token so the rhythm matches OrigamSkeleton.
355
- */
356
- @keyframes origam-switch-skeleton-pulse {
357
- 0%, 100% { opacity: 1; }
358
- 50% { opacity: 0.55; }
359
- }
360
-
361
- .origam-switch__skeleton {
362
- position: relative;
363
- display: inline-block;
364
- width: var(--origam-switch__skeleton---width, 52px);
365
- height: var(--origam-switch__skeleton---height, 32px);
366
- animation: origam-switch-skeleton-pulse 1.6s ease-in-out infinite;
367
-
368
- @media (prefers-reduced-motion: reduce) {
369
- animation: none;
370
- }
371
-
372
- .origam-switch__skeleton-track {
373
- position: absolute;
374
- inset: 0;
375
- border-radius: 999px;
376
- background-color: var(--origam-switch__skeleton-track---background-color, color-mix(in srgb, currentColor 14%, transparent));
377
- }
378
-
379
- .origam-switch__skeleton-thumb {
380
- position: absolute;
381
- top: 50%;
382
- left: 6px;
383
- width: 20px;
384
- height: 20px;
385
- border-radius: 50%;
386
- transform: translateY(-50%);
387
- background-color: var(--origam-switch__skeleton-thumb---background-color, color-mix(in srgb, currentColor 28%, transparent));
388
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
389
- }
390
-
391
- &--inset {
392
- .origam-switch__skeleton-thumb {
393
- /* inset switches use a 24px thumb that overflows the track */
394
- width: 24px;
395
- height: 24px;
396
- left: 4px;
397
- }
398
- }
399
- }
400
-
401
- .origam-switch {
402
- $this: &;
403
-
404
- :deep(.origam-label) {
405
- padding-inline-start: 10px;
406
- }
407
-
408
- /*
409
- * Line loader — thin linear progress positioned ON the track,
410
- * spanning the full switch footprint (46×14 standard or 52×32
411
- * inset). Sits BEHIND the thumb so the thumb stays visually
412
- * dominant and the consumer still sees the on/off position
413
- * while the background indicates async work in flight.
414
- *
415
- * `OrigamProgressLinear` ships an inline `height: thickness`
416
- * (4 px default) that wins over standard CSS — we force it
417
- * to 100 % via `:deep()` so the bar fills the track height
418
- * regardless of the standard / inset variant.
419
- */
420
- &__progress--linear {
421
- position: absolute !important;
422
- inset: 0 !important;
423
- width: 100% !important;
424
- /*
425
- * `OrigamProgressLinear` inlines `height: 4px` on its root via
426
- * `:style="{ height: thickness }"`, which beats any non-important
427
- * scoped rule. `!important` here is the only way to expand the
428
- * loader to the full track height without subclassing the
429
- * progress component.
430
- */
431
- height: 100% !important;
432
- line-height: 1 !important;
433
- border-radius: inherit;
434
- pointer-events: none;
435
- z-index: 0;
436
- overflow: hidden;
437
-
438
- :deep(.origam-progress__background),
439
- :deep(.origam-progress__loader),
440
- :deep(.origam-progress__bar) {
441
- height: 100% !important;
442
- }
443
- }
444
-
445
- &__loader {
446
- display: flex;
447
-
448
- .origam-progress {
449
- color: currentColor;
450
- }
451
- }
452
-
453
- &__thumb {
454
- transition: none;
455
-
456
- @media (forced-colors: active) {
457
- border: 1px solid;
458
- color: buttontext;
459
- }
460
- }
461
-
462
- .origam-selection-control {
463
- min-height: calc(var(--origam-switch__selection-control---min-height, 56px) + var(--origam-input---density, 0px));
464
-
465
- /*
466
- * The base SelectionControl wrapper reserves a fixed
467
- * `calc(40px + 1.5 * density)` box sized for a checkbox/radio
468
- * input glyph. Switch instead renders a variable-width track
469
- * (36–52px depending on `--origam-switch__track---width` /
470
- * the `inset` variant, plus its own horizontal padding) as
471
- * the wrapper's only in-flow child — `__input` is forced
472
- * `position: absolute` below so it no longer participates in
473
- * the flex layout. That fixed formula was never track-aware:
474
- * under `density="compact"` (-8px) the wrapper shrinks to
475
- * 28px while the standard track needs ~46px, so the track
476
- * visually overflows into the neighbouring label ("Flat"
477
- * rendering as "lat"). Let the wrapper size to its actual
478
- * content (`max-content`) instead, keeping the original
479
- * density formula only as a floor via `min-width`/`min-height`
480
- * so the checkbox-sized footprint is preserved whenever the
481
- * track is smaller than it (never smaller than before).
482
- */
483
- :deep(.origam-selection-control__wrapper) {
484
- width: max-content;
485
- height: max-content;
486
- min-width: calc(40px + 1.5 * var(--origam-selection-control--density, 0px));
487
- min-height: calc(40px + 1.5 * var(--origam-selection-control--density, 0px));
488
- }
489
-
490
- :deep(.origam-selection-control__input) {
491
- border-radius: 50%;
492
- transition: 0.2s transform cubic-bezier(0.4, 0, 0.2, 1);
493
- position: absolute;
494
- transform: translateX(-10px);
495
-
496
- .origam-icon {
497
- position: absolute;
498
- }
499
- }
500
-
501
- &--dirty {
502
- :deep(.origam-selection-control__input) {
503
- transform: translateX(10px);
504
- }
505
- }
506
-
507
- &--error {
508
- &:not(.origam-selection-control--disabled) {
509
- #{$this}__thumb {
510
- background-color: rgba(255, 0, 0, 1);
511
- color: rgba(255, 255, 255, 1);
512
- }
513
- }
514
- }
515
- }
516
-
517
- &.origam-input {
518
- flex: 0 1 auto;
519
-
520
- &--vertical {
521
- :deep(.origam-label) {
522
- min-width: max-content;
523
- }
524
-
525
- :deep(.origam-selection-control__wrapper) {
526
- transform: rotate(-90deg);
527
- }
528
- }
529
- }
530
-
531
- .origam-selection-control__wrapper.origam--color-primary &__thumb,
532
- .origam-selection-control__wrapper.origam--color-secondary &__thumb,
533
- .origam-selection-control__wrapper.origam--color-success &__thumb,
534
- .origam-selection-control__wrapper.origam--color-warning &__thumb,
535
- .origam-selection-control__wrapper.origam--color-danger &__thumb,
536
- .origam-selection-control__wrapper.origam--color-info &__thumb,
537
- .origam-selection-control__wrapper.origam--color-neutral &__thumb {
538
- background-color: currentColor;
539
- }
540
-
541
- .origam-selection-control__wrapper[style*="color:"] &__thumb {
542
- background-color: currentColor;
543
- }
544
-
545
- &__thumb {
546
- align-items: center;
547
- background-color: var(--origam-switch__thumb---background-color, rgb(255, 255, 255));
548
- color: var(--origam-switch__thumb---color, currentColor);
549
- border: 1px solid var(--origam-switch__thumb---border-color, rgba(0, 0, 0, 0.18));
550
- border-radius: var(--origam-switch__thumb---border-radius, 50%);
551
- display: flex;
552
- font-size: 0.75rem;
553
- height: var(--origam-switch__thumb---size, 20px);
554
- justify-content: center;
555
- width: var(--origam-switch__thumb---size, 20px);
556
- pointer-events: none;
557
- transition: 0.15s 0.05s transform cubic-bezier(0, 0, 0.2, 1), 0.2s color cubic-bezier(0.4, 0, 0.2, 1), 0.2s background-color cubic-bezier(0.4, 0, 0.2, 1), 0.2s border-color cubic-bezier(0.4, 0, 0.2, 1);
558
- position: relative;
559
- overflow: hidden;
560
-
561
- @media (forced-colors: active) {
562
- background-color: buttontext;
563
- }
564
- }
565
-
566
- &#{$this}--inset {
567
-
568
- #{$this}__thumb {
569
- height: 24px;
570
- width: 24px;
571
- transform: scale(0.6666666667);
572
-
573
- &--filled {
574
- transform: none;
575
- }
576
- }
577
-
578
- .origam-selection-control {
579
- &--dirty {
580
- #{$this}__thumb {
581
- transform: none;
582
- transition: 0.15s 0.05s transform cubic-bezier(0, 0, 0.2, 1);
583
- }
584
- }
585
-
586
- }
587
-
588
- :deep(.origam-selection-control__wrapper) {
589
- width: auto;
590
- }
591
-
592
- &:not(#{$this}--loading) {
593
- &:not(.origam-input--disabled) {
594
- .origam-selection-control--dirty {
595
- #{$this}__thumb {
596
- @media (forced-colors: active) {
597
- background-color: highlighttext;
598
- color: highlighttext;
599
- }
600
- }
601
- }
602
- }
603
- }
604
- }
605
-
606
- &#{$this}--indeterminate {
607
- :deep(.origam-selection-control__input) {
608
- transform: scale(0.8);
609
- }
610
-
611
- #{$this}__thumb {
612
- transform: scale(0.75);
613
- }
614
- }
615
-
616
- &#{$this}--disabled {
617
- #{$this}__thumb {
618
- @media (forced-colors: active) {
619
- background-color: graytext;
620
- color: graytext;
621
- }
622
- }
623
- }
624
-
625
- &#{$this}--loading {
626
- #{$this}__thumb {
627
- @media (forced-colors: active) {
628
- background-color: canvas;
629
- }
630
- }
631
-
632
- &#{$this}--inset,
633
- &#{$this}--indeterminate {
634
- #{$this}__thumb {
635
- @media (forced-colors: active) {
636
- border-width: 0;
637
- }
638
- }
639
- }
640
- }
641
-
642
- &:not(.origam-input--loading) {
643
- &:not(.origam-input--disabled) {
644
- .origam-selection-control--dirty {
645
- #{$this}__thumb {
646
- @media (forced-colors: active) {
647
- background-color: highlight;
648
- }
649
- }
650
- }
651
- }
652
- }
653
-
654
- &:not(.origam-input--disabled) {
655
- .origam-selection-control--dirty {
656
- #{$this}__thumb {
657
- @media (forced-colors: active) {
658
- color: highlight;
659
- }
660
- }
661
- }
662
- }
663
- }
348
+ /*
349
+ * Skeleton placeholder mimicking the switch silhouette — a 52×32
350
+ * rounded track + a 20px circular thumb pinned to the left so the
351
+ * shape is unmistakably a switch (vs the previous plain rectangle
352
+ * which looked like a generic loading bar). Both halves share the
353
+ * `--origam-switch__skeleton-bg` pulse animation inherited from
354
+ * the broader skeleton token so the rhythm matches OrigamSkeleton.
355
+ */
356
+ @keyframes origam-switch-skeleton-pulse {
357
+ 0%, 100% {
358
+ opacity: 1;
359
+ }
360
+ 50% {
361
+ opacity: 0.55;
362
+ }
363
+ }
364
+
365
+ .origam-switch__skeleton {
366
+ position: relative;
367
+ display: inline-block;
368
+ width: var(--origam-switch__skeleton---width, 52px);
369
+ height: var(--origam-switch__skeleton---height, 32px);
370
+ animation: origam-switch-skeleton-pulse 1.6s ease-in-out infinite;
371
+
372
+ @media (prefers-reduced-motion: reduce) {
373
+ animation: none;
374
+ }
375
+
376
+ .origam-switch__skeleton-track {
377
+ position: absolute;
378
+ inset: 0;
379
+ border-radius: 999px;
380
+ background-color: var(--origam-switch__skeleton-track---background-color, color-mix(in srgb, currentColor 14%, transparent));
381
+ }
382
+
383
+ .origam-switch__skeleton-thumb {
384
+ position: absolute;
385
+ top: 50%;
386
+ left: 6px;
387
+ width: 20px;
388
+ height: 20px;
389
+ border-radius: 50%;
390
+ transform: translateY(-50%);
391
+ background-color: var(--origam-switch__skeleton-thumb---background-color, color-mix(in srgb, currentColor 28%, transparent));
392
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
393
+ }
394
+
395
+ &--inset {
396
+ .origam-switch__skeleton-thumb {
397
+ /* inset switches use a 24px thumb that overflows the track */
398
+ width: 24px;
399
+ height: 24px;
400
+ left: 4px;
401
+ }
402
+ }
403
+ }
404
+
405
+ .origam-switch {
406
+ $this: &;
407
+
408
+ :deep(.origam-label) {
409
+ padding-inline-start: 10px;
410
+ }
411
+
412
+ /*
413
+ * Line loader — thin linear progress positioned ON the track,
414
+ * spanning the full switch footprint (46×14 standard or 52×32
415
+ * inset). Sits BEHIND the thumb so the thumb stays visually
416
+ * dominant and the consumer still sees the on/off position
417
+ * while the background indicates async work in flight.
418
+ *
419
+ * `OrigamProgressLinear` ships an inline `height: thickness`
420
+ * (4 px default) that wins over standard CSS — we force it
421
+ * to 100 % via `:deep()` so the bar fills the track height
422
+ * regardless of the standard / inset variant.
423
+ */
424
+ &__progress--linear {
425
+ position: absolute !important;
426
+ inset: 0 !important;
427
+ width: 100% !important;
428
+ /*
429
+ * `OrigamProgressLinear` inlines `height: 4px` on its root via
430
+ * `:style="{ height: thickness }"`, which beats any non-important
431
+ * scoped rule. `!important` here is the only way to expand the
432
+ * loader to the full track height without subclassing the
433
+ * progress component.
434
+ */
435
+ height: 100% !important;
436
+ line-height: 1 !important;
437
+ border-radius: inherit;
438
+ pointer-events: none;
439
+ z-index: 0;
440
+ overflow: hidden;
441
+
442
+ :deep(.origam-progress__background),
443
+ :deep(.origam-progress__loader),
444
+ :deep(.origam-progress__bar) {
445
+ height: 100% !important;
446
+ }
447
+ }
448
+
449
+ &__loader {
450
+ display: flex;
451
+
452
+ .origam-progress {
453
+ color: currentColor;
454
+ }
455
+ }
456
+
457
+ &__thumb {
458
+ transition: none;
459
+
460
+ @media (forced-colors: active) {
461
+ border: 1px solid;
462
+ color: buttontext;
463
+ }
464
+ }
465
+
466
+ .origam-selection-control {
467
+ min-height: calc(var(--origam-switch__selection-control---min-height, 56px) + var(--origam-input---density, 0px));
468
+
469
+ /*
470
+ * The base SelectionControl wrapper reserves a fixed
471
+ * `calc(40px + 1.5 * density)` box sized for a checkbox/radio
472
+ * input glyph. Switch instead renders a variable-width track
473
+ * (36–52px depending on `--origam-switch__track---width` /
474
+ * the `inset` variant, plus its own horizontal padding) as
475
+ * the wrapper's only in-flow child — `__input` is forced
476
+ * `position: absolute` below so it no longer participates in
477
+ * the flex layout. That fixed formula was never track-aware:
478
+ * under `density="compact"` (-8px) the wrapper shrinks to
479
+ * 28px while the standard track needs ~46px, so the track
480
+ * visually overflows into the neighbouring label ("Flat"
481
+ * rendering as "lat"). Let the wrapper size to its actual
482
+ * content (`max-content`) instead, keeping the original
483
+ * density formula only as a floor via `min-width`/`min-height`
484
+ * so the checkbox-sized footprint is preserved whenever the
485
+ * track is smaller than it (never smaller than before).
486
+ */
487
+ :deep(.origam-selection-control__wrapper) {
488
+ width: max-content;
489
+ height: max-content;
490
+ min-width: calc(40px + 1.5 * var(--origam-selection-control--density, 0px));
491
+ min-height: calc(40px + 1.5 * var(--origam-selection-control--density, 0px));
492
+ }
493
+
494
+ :deep(.origam-selection-control__input) {
495
+ border-radius: 50%;
496
+ transition: 0.2s transform cubic-bezier(0.4, 0, 0.2, 1);
497
+ position: absolute;
498
+ transform: translateX(-10px);
499
+
500
+ .origam-icon {
501
+ position: absolute;
502
+ }
503
+ }
504
+
505
+ &--dirty {
506
+ :deep(.origam-selection-control__input) {
507
+ transform: translateX(10px);
508
+ }
509
+ }
510
+
511
+ &--error {
512
+ &:not(.origam-selection-control--disabled) {
513
+ #{$this}__thumb {
514
+ background-color: rgba(255, 0, 0, 1);
515
+ color: rgba(255, 255, 255, 1);
516
+ }
517
+ }
518
+ }
519
+ }
520
+
521
+ &.origam-input {
522
+ flex: 0 1 auto;
523
+
524
+ &--vertical {
525
+ :deep(.origam-label) {
526
+ min-width: max-content;
527
+ }
528
+
529
+ :deep(.origam-selection-control__wrapper) {
530
+ transform: rotate(-90deg);
531
+ }
532
+ }
533
+ }
534
+
535
+ .origam-selection-control__wrapper.origam--color-primary &__thumb,
536
+ .origam-selection-control__wrapper.origam--color-secondary &__thumb,
537
+ .origam-selection-control__wrapper.origam--color-success &__thumb,
538
+ .origam-selection-control__wrapper.origam--color-warning &__thumb,
539
+ .origam-selection-control__wrapper.origam--color-danger &__thumb,
540
+ .origam-selection-control__wrapper.origam--color-info &__thumb,
541
+ .origam-selection-control__wrapper.origam--color-neutral &__thumb {
542
+ background-color: currentColor;
543
+ }
544
+
545
+ .origam-selection-control__wrapper[style*="color:"] &__thumb {
546
+ background-color: currentColor;
547
+ }
548
+
549
+ &__thumb {
550
+ align-items: center;
551
+ background-color: var(--origam-switch__thumb---background-color, rgb(255, 255, 255));
552
+ color: var(--origam-switch__thumb---color, currentColor);
553
+ border: 1px solid var(--origam-switch__thumb---border-color, rgba(0, 0, 0, 0.18));
554
+ border-radius: var(--origam-switch__thumb---border-radius, 50%);
555
+ display: flex;
556
+ font-size: 0.75rem;
557
+ height: var(--origam-switch__thumb---size, 20px);
558
+ justify-content: center;
559
+ width: var(--origam-switch__thumb---size, 20px);
560
+ pointer-events: none;
561
+ transition: 0.15s 0.05s transform cubic-bezier(0, 0, 0.2, 1), 0.2s color cubic-bezier(0.4, 0, 0.2, 1), 0.2s background-color cubic-bezier(0.4, 0, 0.2, 1), 0.2s border-color cubic-bezier(0.4, 0, 0.2, 1);
562
+ position: relative;
563
+ overflow: hidden;
564
+
565
+ @media (forced-colors: active) {
566
+ background-color: buttontext;
567
+ }
568
+ }
569
+
570
+ &#{$this}--inset {
571
+
572
+ #{$this}__thumb {
573
+ height: 24px;
574
+ width: 24px;
575
+ transform: scale(0.6666666667);
576
+
577
+ &--filled {
578
+ transform: none;
579
+ }
580
+ }
581
+
582
+ .origam-selection-control {
583
+ &--dirty {
584
+ #{$this}__thumb {
585
+ transform: none;
586
+ transition: 0.15s 0.05s transform cubic-bezier(0, 0, 0.2, 1);
587
+ }
588
+ }
589
+
590
+ }
591
+
592
+ :deep(.origam-selection-control__wrapper) {
593
+ width: auto;
594
+ }
595
+
596
+ &:not(#{$this}--loading) {
597
+ &:not(.origam-input--disabled) {
598
+ .origam-selection-control--dirty {
599
+ #{$this}__thumb {
600
+ @media (forced-colors: active) {
601
+ background-color: highlighttext;
602
+ color: highlighttext;
603
+ }
604
+ }
605
+ }
606
+ }
607
+ }
608
+ }
609
+
610
+ &#{$this}--indeterminate {
611
+ :deep(.origam-selection-control__input) {
612
+ transform: scale(0.8);
613
+ }
614
+
615
+ #{$this}__thumb {
616
+ transform: scale(0.75);
617
+ }
618
+ }
619
+
620
+ &#{$this}--disabled {
621
+ #{$this}__thumb {
622
+ @media (forced-colors: active) {
623
+ background-color: graytext;
624
+ color: graytext;
625
+ }
626
+ }
627
+ }
628
+
629
+ &#{$this}--loading {
630
+ #{$this}__thumb {
631
+ @media (forced-colors: active) {
632
+ background-color: canvas;
633
+ }
634
+ }
635
+
636
+ &#{$this}--inset,
637
+ &#{$this}--indeterminate {
638
+ #{$this}__thumb {
639
+ @media (forced-colors: active) {
640
+ border-width: 0;
641
+ }
642
+ }
643
+ }
644
+ }
645
+
646
+ &:not(.origam-input--loading) {
647
+ &:not(.origam-input--disabled) {
648
+ .origam-selection-control--dirty {
649
+ #{$this}__thumb {
650
+ @media (forced-colors: active) {
651
+ background-color: highlight;
652
+ }
653
+ }
654
+ }
655
+ }
656
+ }
657
+
658
+ &:not(.origam-input--disabled) {
659
+ .origam-selection-control--dirty {
660
+ #{$this}__thumb {
661
+ @media (forced-colors: active) {
662
+ color: highlight;
663
+ }
664
+ }
665
+ }
666
+ }
667
+ }
664
668
  </style>