origam 2.8.1 → 2.10.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 (50) hide show
  1. package/dist/src/assets/css/main.css +1 -1
  2. package/dist/src/assets/css/tokens/dark.css +38 -4
  3. package/dist/src/assets/css/tokens/light.css +19 -2
  4. package/dist/src/assets/scss/tokens/_dark.scss +19 -2
  5. package/dist/src/assets/scss/tokens/_light.scss +19 -2
  6. package/dist/src/components/Alert/OrigamAlert.vue +4 -2
  7. package/dist/src/components/App/OrigamApp.vue +7 -6
  8. package/dist/src/components/Avatar/OrigamAvatarGroup.vue +31 -12
  9. package/dist/src/components/Btn/OrigamBtn.vue +11 -2
  10. package/dist/src/components/Btn/OrigamBtnGroup.vue +204 -22
  11. package/dist/src/components/Btn/OrigamBtnToggle.vue +5 -1
  12. package/dist/src/components/Card/OrigamCard.vue +5 -2
  13. package/dist/src/components/Checkbox/OrigamCheckbox.vue +3 -1
  14. package/dist/src/components/Chip/OrigamChip.vue +2 -0
  15. package/dist/src/components/Code/OrigamCode.vue +4 -2
  16. package/dist/src/components/ColorPicker/OrigamColorPickerPreview.vue +1 -1
  17. package/dist/src/components/ColorPickerField/OrigamColorPickerField.vue +52 -2
  18. package/dist/src/components/DatePickerField/OrigamDatePickerField.vue +32 -2
  19. package/dist/src/components/Dialog/OrigamDialog.vue +1 -1
  20. package/dist/src/components/Field/OrigamField.vue +39 -3
  21. package/dist/src/components/Layout/OrigamLayout.vue +10 -1
  22. package/dist/src/components/Menu/OrigamMenu.vue +3 -1
  23. package/dist/src/components/NumberField/OrigamNumberField.vue +3 -2
  24. package/dist/src/components/Overlay/OrigamOverlayScrim.vue +2 -0
  25. package/dist/src/components/Radio/OrigamRadio.vue +3 -1
  26. package/dist/src/components/Select/OrigamSelect.vue +3 -1
  27. package/dist/src/components/SelectionControl/OrigamSelectionControl.vue +2 -0
  28. package/dist/src/components/SliderField/OrigamSliderField.vue +26 -13
  29. package/dist/src/components/Snackbar/OrigamSnackbar.vue +3 -1
  30. package/dist/src/components/Snackbar/OrigamSnackbarItem.vue +2 -0
  31. package/dist/src/components/Switch/OrigamSwitch.vue +42 -1
  32. package/dist/src/components/Switch/OrigamSwitchTrack.vue +35 -2
  33. package/dist/src/components/Table/OrigamTable.vue +4 -2
  34. package/dist/src/components/Tabs/OrigamTabs.vue +3 -1
  35. package/dist/src/components/Tooltip/OrigamTooltip.vue +2 -0
  36. package/dist/src/composables/Commons/defaults.composable.cjs +10 -6
  37. package/dist/src/composables/Commons/defaults.composable.d.ts +30 -0
  38. package/dist/src/composables/Commons/defaults.composable.js +9 -6
  39. package/dist/src/composables/Theme/theme.composable.cjs +49 -30
  40. package/dist/src/composables/Theme/theme.composable.js +41 -22
  41. package/dist/src/interfaces/App/app.interface.d.ts +1 -1
  42. package/dist/src/interfaces/Btn/btn-group.interface.d.ts +2 -2
  43. package/dist/src/interfaces/Switch/switch-track.interface.d.ts +23 -6
  44. package/dist/src/themes/origam.theme.cjs +2 -4
  45. package/dist/src/themes/origam.theme.js +2 -2
  46. package/dist/src/types/tokens.type.d.ts +1 -1
  47. package/dist/src/utils/Commons/commons.util.cjs +10 -0
  48. package/dist/src/utils/Commons/commons.util.d.ts +18 -0
  49. package/dist/src/utils/Commons/commons.util.js +9 -0
  50. package/package.json +1 -1
@@ -180,12 +180,12 @@ import {
180
180
  OrigamTextField,
181
181
  OrigamTranslateScale
182
182
  } from "../../components";
183
- import { useDate, useLocale, useProps, useTextColor, useVModel, useStyle } from "../../composables";
183
+ import { useDate, useDefaults, useLocale, useProps, useTextColor, useVModel, useStyle } from "../../composables";
184
184
  import { ORIGAM_FORM_KEY } from "../../consts";
185
185
  import { BLOCK, DENSITY, DIRECTION, KEYBOARD_VALUES, MDI_ICONS, TEXT_FIELD_TYPE } from "../../enums";
186
186
  import { forwardRefs, isEmpty, matchesSelector, wrapInArray } from "../../utils";
187
187
  import { computed, inject, nextTick, ref, shallowRef, StyleValue, toRef, useSlots, watch } from "vue";
188
- const props = defineProps({
188
+ const _props = defineProps({
189
189
  menu: { type: Boolean, required: false },
190
190
  menuProps: { type: Object, required: false },
191
191
  range: { type: Boolean, required: false, default: false },
@@ -307,6 +307,7 @@ const props = defineProps({
307
307
  prependIcon: { type: null, required: false },
308
308
  transition: { type: [Boolean, String, Object], required: false, default: () => ({ component: OrigamTranslateScale }) }
309
309
  });
310
+ const props = useDefaults(_props);
310
311
  const { filterProps } = useProps(props);
311
312
  const { t } = useLocale();
312
313
  const origamTextFieldRef = ref();
@@ -508,3 +509,32 @@ defineExpose(forwardRefs({
508
509
  isLoaded
509
510
  }, origamTextFieldRef));
510
511
  </script>
512
+
513
+ <style lang="scss" scoped>
514
+ .origam-date-picker-field {
515
+ :deep(.origam-date-picker-field__selection-text) {
516
+ overflow: hidden;
517
+ text-overflow: ellipsis;
518
+ white-space: nowrap;
519
+ min-width: 0;
520
+ }
521
+
522
+ // Same single-line fix as OrigamSelect / OrigamColorPickerField: the
523
+ // underlying native `<input>` is taken OUT of flow so it can't sit
524
+ // beside the formatted `selectionText`/`rangeSelection` span and push
525
+ // the field onto a second line. The span is the real display value;
526
+ // the input only carries focus / the editable value. `nowrap` alone
527
+ // is insufficient — the in-flow input still forces a wrap in a
528
+ // narrow container (confirmed: 61px vs 36px at 150px width on the
529
+ // range variant).
530
+ :deep(.origam-field__input) {
531
+ flex-wrap: nowrap;
532
+
533
+ > input {
534
+ position: absolute;
535
+ flex: 0 0;
536
+ min-width: 0;
537
+ }
538
+ }
539
+ }
540
+ </style>
@@ -184,7 +184,7 @@ const props = defineProps({
184
184
  contained: { type: Boolean, required: false },
185
185
  eager: { type: Boolean, required: false },
186
186
  transition: { type: [Boolean, String, Object], required: false, default: () => ({ component: OrigamTranslateScale }) },
187
- scrim: { type: [Boolean, String], required: false },
187
+ scrim: { type: [Boolean, String], required: false, default: true },
188
188
  flat: { type: Boolean, required: false },
189
189
  hover: { type: Boolean, required: false },
190
190
  image: { type: String, required: false },
@@ -519,7 +519,16 @@ defineExpose({
519
519
  flex: 1 0;
520
520
  grid-area: control;
521
521
  position: relative;
522
- padding-inline: var(--origam-field---padding-start) var(--origam-field---padding-end);
522
+ // Corner-clearing: when the corner radius is larger than the inline
523
+ // padding, the text / floating label collide with the rounded outline.
524
+ // Floor the inline padding at the effective radius (capped at the control
525
+ // height for pills). Prepended fields opt out below — their prepend icon
526
+ // already fills the corner.
527
+ padding-inline:
528
+ max(var(--origam-field---padding-start), min(var(--origam-field---border-radius, 8px), var(--origam-input__control---height, 36px)))
529
+ var(--origam-field---padding-end);
530
+ backdrop-filter: var(--origam-field---backdrop-filter, none);
531
+ -webkit-backdrop-filter: var(--origam-field---backdrop-filter, none);
523
532
 
524
533
  &__skeleton {
525
534
  width: 100%;
@@ -702,7 +711,7 @@ defineExpose({
702
711
 
703
712
  #{$this}__outline {
704
713
  &--start {
705
- flex: 0 0 var(--origam-field---padding-start);
714
+ flex: 0 0 max(var(--origam-field---padding-start), min(var(--origam-field---border-radius, 8px), var(--origam-input__control---height, 36px)));
706
715
  }
707
716
 
708
717
  &--end {
@@ -773,6 +782,16 @@ defineExpose({
773
782
 
774
783
  &--prepended {
775
784
  --origam-field---padding-start: 6px;
785
+
786
+ // A prepend-inner (icon / swatch) already fills the left corner, so
787
+ // opt out of the corner-clearing floor: keep the inline padding and
788
+ // the start outline leg at the raw padding-start (widening them would
789
+ // draw the outline over the prepend content).
790
+ padding-inline: var(--origam-field---padding-start) var(--origam-field---padding-end);
791
+
792
+ #{$this}__outline--start {
793
+ flex-basis: var(--origam-field---padding-start);
794
+ }
776
795
  }
777
796
 
778
797
  &--appended {
@@ -788,6 +807,11 @@ defineExpose({
788
807
  #{$this}__label {
789
808
  opacity: 1;
790
809
  }
810
+
811
+ &:not(#{$this}--disabled) {
812
+ outline: var(--origam-field---focus-ring-width, 0px) solid var(--origam-field---focus-ring-color, transparent);
813
+ outline-offset: var(--origam-field---focus-ring-offset, 0px);
814
+ }
791
815
  }
792
816
 
793
817
  &--disabled,
@@ -967,7 +991,19 @@ defineExpose({
967
991
  &#{$this}__label--floating {
968
992
  transform: translateY(-50%);
969
993
  transform-origin: center;
970
- margin: 0 4px;
994
+ // Align the floating label's inline-start with the input
995
+ // text (and the resting label), both of which sit at
996
+ // `--origam-field__input---padding-start`. The old hard
997
+ // `margin: 0 4px` pinned the floating label to the notch
998
+ // corner instead, leaving it inset by (input-padding − 4)
999
+ // px LESS than the value — a visible label/value
1000
+ // misalignment that grows with the corner radius (most
1001
+ // obvious on large-radius themes, e.g. cartoon `rounded-lg`,
1002
+ // where it read as "the input is more indented than the
1003
+ // label"). Keep the 4px on the inline-end for notch
1004
+ // breathing room.
1005
+ margin-block: 0;
1006
+ margin-inline: var(--origam-field__input---padding-start, 0) 4px;
971
1007
  }
972
1008
  }
973
1009
 
@@ -151,8 +151,17 @@ defineExpose({
151
151
  }
152
152
 
153
153
  &--full-height &__wrapper {
154
+ // `min-height` (not `height`) — full-height means "occupy AT
155
+ // LEAST the viewport", not "clip to exactly the viewport".
156
+ // A fixed `height: 100vh` kept the wrapper's own box capped
157
+ // at one screen even when its content (app-bar + main slot)
158
+ // grows taller — the overflow still rendered (no
159
+ // `overflow: hidden` here) but the wrapper's box, and
160
+ // anything painting a background on an ancestor sized off
161
+ // it, never grew to match, leaving a visible gap below the
162
+ // first viewport on any page taller than one screen.
154
163
  width: 100vw;
155
- height: 100vh;
164
+ min-height: 100vh;
156
165
  }
157
166
  }
158
167
  </style>
@@ -81,6 +81,7 @@ import {
81
81
  } from "../../components";
82
82
  import {
83
83
  useBothColor,
84
+ useDefaults,
84
85
  useProps,
85
86
  useScopeId,
86
87
  useStateEffect,
@@ -90,7 +91,7 @@ import {
90
91
  import { ORIGAM_MENU_KEY } from "../../consts";
91
92
  import { INLINE, KEYBOARD_VALUES, LOCATION_STRATEGIES, MDI_ICONS, SCROLL_STRATEGIES } from "../../enums";
92
93
  import { focusableChildren, focusChild, forwardRefs, getNextElement, getUid } from "../../utils";
93
- const props = defineProps({
94
+ const _props = defineProps({
94
95
  id: { type: String, required: false },
95
96
  absolute: { type: Boolean, required: false },
96
97
  attach: { type: [Boolean, String], required: false, skipCheck: true },
@@ -208,6 +209,7 @@ const props = defineProps({
208
209
  lineHeight: { type: String, required: false },
209
210
  letterSpacing: { type: String, required: false }
210
211
  });
212
+ const props = useDefaults(_props);
211
213
  defineEmits(["contextmenu", "update:modelValue"]);
212
214
  const { filterProps } = useProps(props);
213
215
  const { colorClasses, colorStyles } = useBothColor(toRef(props, "bgColor"), toRef(props, "color"));
@@ -269,10 +269,10 @@
269
269
  <script lang="ts" setup>
270
270
  import { computed, nextTick, onMounted, ref, shallowRef, StyleValue, useSlots, watch } from "vue";
271
271
  import { OrigamBtn, OrigamDivider, OrigamInput, OrigamTextField } from "../../components";
272
- import { useAdjacentInner, useFocus, useHold, useProps, useVModel, useStyle } from "../../composables";
272
+ import { useAdjacentInner, useDefaults, useFocus, useHold, useProps, useVModel, useStyle } from "../../composables";
273
273
  import { DIRECTION, MDI_ICONS, TEXT_FIELD_TYPE } from "../../enums";
274
274
  import { clamp, forwardRefs } from "../../utils";
275
- const props = defineProps({
275
+ const _props = defineProps({
276
276
  autofocus: { type: Boolean, required: false },
277
277
  placeholder: { type: String, required: false },
278
278
  persistentPlaceholder: { type: Boolean, required: false },
@@ -391,6 +391,7 @@ const props = defineProps({
391
391
  prependAvatar: { type: String, required: false },
392
392
  prependIcon: { type: null, required: false }
393
393
  });
394
+ const props = useDefaults(_props);
394
395
  const emits = defineEmits(["click:control", "mousedown:control", "click:clear", "increment", "decrement", "update:focused", "update:modelValue", "click:appendInner", "click:prependInner", "update:active", "click:append", "click:prepend"]);
395
396
  defineSlots();
396
397
  const { filterProps } = useProps(props);
@@ -72,6 +72,8 @@ defineExpose({
72
72
  <style lang="scss" scoped>
73
73
  .origam-scrim {
74
74
  background-color: var(--origam-overlay-scrim---background-color, var(--origam-color__overlay---scrim)); // TODO: rename to color.overlay.backdrop once #arbitration2 resolved
75
+ backdrop-filter: var(--origam-overlay-scrim---backdrop-filter, none);
76
+ -webkit-backdrop-filter: var(--origam-overlay-scrim---backdrop-filter, none);
75
77
  pointer-events: var(--origam-overlay-scrim---pointer-events, auto);
76
78
  border-radius: inherit;
77
79
  inset: 0;
@@ -103,6 +103,7 @@
103
103
  import { computed, ref, StyleValue, useAttrs, useSlots } from "vue";
104
104
  import { OrigamInput, OrigamRadioBtn } from "../../components";
105
105
  import {
106
+ useDefaults,
106
107
  useFocus,
107
108
  useHover,
108
109
  useMargin,
@@ -114,7 +115,7 @@ import {
114
115
  } from "../../composables";
115
116
  import { DENSITY } from "../../enums";
116
117
  import { filterInputAttrs, getUid } from "../../utils";
117
- const props = defineProps({
118
+ const _props = defineProps({
118
119
  id: { type: String, required: false },
119
120
  class: { type: [String, Array, Object], required: false },
120
121
  style: { type: [String, Array, Object, Boolean, null], required: false, skipCheck: true },
@@ -206,6 +207,7 @@ const props = defineProps({
206
207
  activeClass: { type: String, required: false },
207
208
  hover: { type: [Boolean, Object], required: false }
208
209
  });
210
+ const props = useDefaults(_props);
209
211
  const emits = defineEmits(["update:modelValue", "update:focused", "click:label"]);
210
212
  const { isHover, hoverState } = useHover(props);
211
213
  useStateEffect(props, isHover, void 0, hoverState, void 0);
@@ -289,6 +289,7 @@ import {
289
289
  OrigamVirtualScroll
290
290
  } from "../../components";
291
291
  import {
292
+ useDefaults,
292
293
  useFilter,
293
294
  useItems,
294
295
  useLocale,
@@ -310,7 +311,7 @@ import {
310
311
  TEXT_FIELD_TYPE
311
312
  } from "../../enums";
312
313
  import { deepEqual, forwardRefs, getUid, matchesSelector, noop, wrapInArray } from "../../utils";
313
- const props = defineProps({
314
+ const _props = defineProps({
314
315
  chips: { type: Boolean, required: false },
315
316
  closableChips: { type: Boolean, required: false },
316
317
  hideNoData: { type: Boolean, required: false },
@@ -454,6 +455,7 @@ const props = defineProps({
454
455
  noFilter: { type: Boolean, required: false },
455
456
  eager: { type: Boolean, required: false }
456
457
  });
458
+ const props = useDefaults(_props);
457
459
  defineEmits(["click:control", "mousedown:control", "update:menu", "update:modelValue", "update:focused", "click:append", "click:prepend", "click:appendInner", "click:prependInner", "click:clear"]);
458
460
  const { filterProps } = useProps(props);
459
461
  const { t } = useLocale();
@@ -283,6 +283,8 @@ defineExpose(forwardRefs({
283
283
  justify-content: center;
284
284
  position: relative;
285
285
  border-radius: 50%;
286
+ backdrop-filter: var(--origam-selection-control__input---backdrop-filter, none);
287
+ -webkit-backdrop-filter: var(--origam-selection-control__input---backdrop-filter, none);
286
288
 
287
289
  > .origam-icon {
288
290
  opacity: 0.7;
@@ -44,6 +44,7 @@
44
44
  :is-vertical="isVertical"
45
45
  :max="resolvedMax"
46
46
  :min="resolvedMin"
47
+ :rounded="resolvedRounded"
47
48
  :show-ticks="showTicks"
48
49
  :start="isRange ? trackRangeStart : 0"
49
50
  :stop="isRange ? trackRangeStop : trackStop"
@@ -273,6 +274,7 @@
273
274
  :is-vertical="isVertical"
274
275
  :max="resolvedMax"
275
276
  :min="resolvedMin"
277
+ :rounded="resolvedRounded"
276
278
  :show-ticks="showTicks"
277
279
  :start="isRange ? trackRangeStart : 0"
278
280
  :stop="isRange ? trackRangeStop : trackStop"
@@ -423,8 +425,10 @@ import { computed, ref, StyleValue, useSlots, WritableComputedRef } from "vue";
423
425
  import { OrigamInput, OrigamLabel, OrigamSliderFieldTrack } from "../../components";
424
426
  import {
425
427
  useBackgroundColor,
428
+ useDefaults,
426
429
  useFocus,
427
430
  useProps,
431
+ useRounded,
428
432
  useRtl,
429
433
  useSteps,
430
434
  useStyle,
@@ -433,7 +437,7 @@ import {
433
437
  } from "../../composables";
434
438
  import { DENSITY, DIRECTION, SLIDER_FIELD_VARIANT } from "../../enums";
435
439
  import { clamp, convertToUnit, createRange, omit } from "../../utils";
436
- const props = defineProps({
440
+ const _props = defineProps({
437
441
  disabled: { type: Boolean, required: false },
438
442
  required: { type: Boolean, required: false },
439
443
  label: { type: String, required: false },
@@ -527,6 +531,7 @@ const props = defineProps({
527
531
  letterSpacing: { type: String, required: false },
528
532
  ripple: { type: [Boolean, Object], required: false }
529
533
  });
534
+ const props = useDefaults(_props);
530
535
  const emits = defineEmits(["start", "end", "update:modelValue", "update:focused"]);
531
536
  const { filterProps } = useProps(props);
532
537
  const origamInputRef = ref();
@@ -582,12 +587,14 @@ const bufferedPercentage = computed(() => {
582
587
  const clamped = clamp(props.buffered, resolvedMin.value, resolvedMax.value);
583
588
  return toPercent(clamped);
584
589
  });
585
- const bufferedStyles = computed(() => {
590
+ const bufferedPosition = computed(() => {
586
591
  const pct = bufferedPercentage.value;
587
- if (isVertical.value) {
588
- return { height: `${pct}%`, bottom: "0" };
589
- }
590
- return indexFromEnd.value ? { width: `${pct}%`, insetInlineEnd: "0" } : { width: `${pct}%`, insetInlineStart: "0" };
592
+ if (isVertical.value) return { height: `${pct}%`, bottom: "0" };
593
+ if (indexFromEnd.value) return { width: `${pct}%`, insetInlineEnd: "0" };
594
+ return { width: `${pct}%`, insetInlineStart: "0" };
595
+ });
596
+ const bufferedStyles = computed(() => {
597
+ return [bufferedPosition.value, roundedStyles.value];
591
598
  });
592
599
  const hasPeaks = computed(() => {
593
600
  if (!isAudioVariant.value) return false;
@@ -765,6 +772,10 @@ const bgColor = computed(() => {
765
772
  });
766
773
  const { backgroundColorClasses: thumbBgClasses, backgroundColorStyles: thumbBgStyles } = useBackgroundColor(color);
767
774
  const { textColorClasses: thumbTextClasses, textColorStyles: thumbTextStyles } = useTextColor(color);
775
+ const resolvedRounded = computed(() => {
776
+ return props.trackProps?.rounded ?? props.rounded;
777
+ });
778
+ const { roundedClasses, roundedStyles } = useRounded(resolvedRounded);
768
779
  const inputProps = computed(() => {
769
780
  return origamInputRef.value?.filterProps(props, ["modelValue", "class", "style", "id", "focused", "centerAffix", "color", "bgColor", "activeColor", "activeBgColor", "hoverColor", "hoverBgColor"]);
770
781
  });
@@ -843,6 +854,7 @@ const sliderFieldClasses = computed(() => {
843
854
  variantClass.value,
844
855
  sharedStateClasses.value,
845
856
  rtlClasses.value,
857
+ roundedClasses.value,
846
858
  props.class
847
859
  ];
848
860
  });
@@ -853,6 +865,7 @@ const bareWrapperClasses = computed(() => {
853
865
  variantClass.value,
854
866
  sharedStateClasses.value,
855
867
  rtlClasses.value,
868
+ roundedClasses.value,
856
869
  props.class
857
870
  ];
858
871
  });
@@ -962,7 +975,7 @@ defineExpose({
962
975
  pointer-events: none;
963
976
  background: var(--origam-slider-field__buffered---background-color, color-mix(in srgb, currentColor 40%, transparent));
964
977
  opacity: var(--origam-slider-field__buffered---opacity, 0.5);
965
- border-radius: 999px;
978
+ border-radius: var(--origam-slider-field---border-radius, 999px);
966
979
  top: 50%;
967
980
  transform: translateY(-50%);
968
981
  height: var(--origam-slider-field--variant--field---track-thickness, var(--origam-slider-field---track-size, 4px));
@@ -1185,15 +1198,15 @@ defineExpose({
1185
1198
 
1186
1199
  :deep(.origam-slider-field-track) {
1187
1200
  background: transparent;
1188
- border-radius: 999px;
1201
+ border-radius: var(--origam-slider-field---border-radius, 999px);
1189
1202
  }
1190
1203
 
1191
1204
  :deep(.origam-slider-field-track__background) {
1192
- border-radius: 999px;
1205
+ border-radius: var(--origam-slider-field---border-radius, 999px);
1193
1206
  }
1194
1207
 
1195
1208
  :deep(.origam-slider-field-track__fill) {
1196
- border-radius: 999px;
1209
+ border-radius: var(--origam-slider-field---border-radius, 999px);
1197
1210
  }
1198
1211
 
1199
1212
  &.origam-slider-field--horizontal {
@@ -1261,7 +1274,7 @@ defineExpose({
1261
1274
 
1262
1275
  :deep(.origam-slider-field-track) {
1263
1276
  background-color: var(--origam-slider-field--bare---track-background-color, color-mix(in srgb, currentColor 25%, transparent));
1264
- border-radius: 999px;
1277
+ border-radius: var(--origam-slider-field---border-radius, 999px);
1265
1278
  height: var(--origam-slider-field--variant--field---track-thickness);
1266
1279
  width: 100%;
1267
1280
  transition: height 140ms ease;
@@ -1274,14 +1287,14 @@ defineExpose({
1274
1287
  .origam-slider-field-track__fill {
1275
1288
  background: currentColor;
1276
1289
  height: 100%;
1277
- border-radius: 999px;
1290
+ border-radius: var(--origam-slider-field---border-radius, 999px);
1278
1291
  }
1279
1292
  }
1280
1293
 
1281
1294
  .origam-slider-field__buffered {
1282
1295
  background: var(--origam-slider-field__buffered--bare---background-color, color-mix(in srgb, currentColor 40%, transparent));
1283
1296
  opacity: 1;
1284
- border-radius: 999px;
1297
+ border-radius: var(--origam-slider-field---border-radius, 999px);
1285
1298
  height: var(--origam-slider-field--variant--field---track-thickness);
1286
1299
  z-index: 1;
1287
1300
  }
@@ -91,6 +91,7 @@ import { OrigamOverlay, OrigamSnack } from "../../components";
91
91
  import OrigamSnackbarItem from "./OrigamSnackbarItem.vue";
92
92
  import {
93
93
  useBothColor,
94
+ useDefaults,
94
95
  useLayout,
95
96
  usePosition,
96
97
  useProps,
@@ -104,7 +105,7 @@ import {
104
105
  import { ORIGAM_LAYOUT_KEY } from "../../consts";
105
106
  import { SCROLL_STRATEGIES } from "../../enums";
106
107
  import { forwardRefs } from "../../utils";
107
- const props = defineProps({
108
+ const _props = defineProps({
108
109
  multiLine: { type: Boolean, required: false },
109
110
  text: { type: String, required: false },
110
111
  timer: { type: [Boolean, String], required: false },
@@ -200,6 +201,7 @@ const props = defineProps({
200
201
  activeClass: { type: String, required: false },
201
202
  hover: { type: [Boolean, Object], required: false }
202
203
  });
204
+ const props = useDefaults(_props);
203
205
  const { filterProps } = useProps(props);
204
206
  const slots = useSlots();
205
207
  const isActive = useVModel(props, "modelValue");
@@ -168,6 +168,8 @@ defineExpose({ filterProps });
168
168
  border-color: var(--origam-snackbar-item---border-color, var(--origam-color__border---subtle, rgba(0, 0, 0, 0.12)));
169
169
  color: var(--origam-snackbar-item---color, var(--origam-color__text---primary, #1a1a1a));
170
170
  box-shadow: var(--origam-snackbar-item---box-shadow, 0 4px 12px rgba(0, 0, 0, 0.12));
171
+ backdrop-filter: var(--origam-snackbar-item---backdrop-filter, none);
172
+ -webkit-backdrop-filter: var(--origam-snackbar-item---backdrop-filter, none);
171
173
  font-size: var(--origam-snackbar-item---font-size, 0.875rem);
172
174
  line-height: 1.4;
173
175
 
@@ -39,6 +39,7 @@
39
39
  >
40
40
  <template #default="{bgColor: scBgColor}">
41
41
  <origam-switch-track
42
+ ref="origamSwitchTrackRef"
42
43
  :bg-color="scBgColor"
43
44
  :disabled="isDisabled"
44
45
  :error="isValid === false"
@@ -46,6 +47,7 @@
46
47
  :is-valid="isValid"
47
48
  :model-value="model"
48
49
  :readonly="isReadonly"
50
+ v-bind="{ ...trackProps }"
49
51
  @click="handleTrackClick"
50
52
  >
51
53
  <template
@@ -97,6 +99,7 @@
97
99
  />
98
100
  <div
99
101
  :class="getSwitchThumbClasses(icon)"
102
+ :style="switchThumbStyles"
100
103
  >
101
104
  <origam-translate-scale>
102
105
  <div
@@ -142,17 +145,19 @@ import {
142
145
  OrigamTranslateScale
143
146
  } from "../../components";
144
147
  import {
148
+ useDefaults,
145
149
  useFocus,
146
150
  useHover,
147
151
  useLoader,
148
152
  useProps,
153
+ useRounded,
149
154
  useStateEffect,
150
155
  useStyle,
151
156
  useVModel
152
157
  } from "../../composables";
153
158
  import { DENSITY, PROGRESS_TYPE, SIZES } from "../../enums";
154
159
  import { filterInputAttrs, getUid } from "../../utils";
155
- const props = defineProps({
160
+ const _props = defineProps({
156
161
  indeterminate: { type: Boolean, required: false },
157
162
  inset: { type: Boolean, required: false },
158
163
  flat: { type: Boolean, required: false },
@@ -250,12 +255,14 @@ const props = defineProps({
250
255
  loading: { type: [Boolean, Number, Object], required: false },
251
256
  loadingText: { type: String, required: false }
252
257
  });
258
+ const props = useDefaults(_props);
253
259
  defineEmits(["update:modelValue", "update:focused", "update:indeterminate", "click:label"]);
254
260
  const { isHover, hoverState } = useHover(props);
255
261
  useStateEffect(props, isHover, void 0, hoverState, void 0);
256
262
  const { filterProps } = useProps(props);
257
263
  const origamSelectionControlRef = ref();
258
264
  const origamInputRef = ref();
265
+ const origamSwitchTrackRef = ref();
259
266
  const indeterminate = useVModel(props, "indeterminate");
260
267
  const model = useVModel(props, "modelValue");
261
268
  const { isFocused, onFocus: handleFocus, onBlur: handleBlur } = useFocus(props);
@@ -282,6 +289,9 @@ const inputProps = computed(() => {
282
289
  const controlProps = computed(() => {
283
290
  return origamSelectionControlRef.value?.filterProps(props, ["modelValue", "type", "disabled", "readonly", "class", "style", "id"]);
284
291
  });
292
+ const trackProps = computed(() => {
293
+ return origamSwitchTrackRef.value?.filterProps(props, ["modelValue", "disabled", "readonly", "error", "inset", "isValid", "bgColor", "color", "class", "style", "id"]);
294
+ });
285
295
  const isSkeletonLoading = computed(() => {
286
296
  return loaderConfig.value.isActive && loaderConfig.value.kind === "skeleton";
287
297
  });
@@ -298,6 +308,12 @@ const switchStyles = computed(() => {
298
308
  props.style
299
309
  ];
300
310
  });
311
+ const { roundedStyles: thumbRoundedStyles } = useRounded(props, "origam-switch__thumb");
312
+ const switchThumbStyles = computed(() => {
313
+ return [
314
+ thumbRoundedStyles.value
315
+ ];
316
+ });
301
317
  const getSwitchThumbClasses = (icon) => {
302
318
  return [
303
319
  "origam-switch__thumb",
@@ -446,6 +462,31 @@ defineExpose({
446
462
  .origam-selection-control {
447
463
  min-height: calc(var(--origam-switch__selection-control---min-height, 56px) + var(--origam-input---density, 0px));
448
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
+
449
490
  :deep(.origam-selection-control__input) {
450
491
  border-radius: 50%;
451
492
  transition: 0.2s transform cubic-bezier(0.4, 0, 0.2, 1);
@@ -37,7 +37,10 @@
37
37
  import { computed, StyleValue, useSlots } from "vue";
38
38
  import {
39
39
  useBackgroundColor,
40
+ useBorder,
41
+ useElevation,
40
42
  useProps,
43
+ useRounded,
41
44
  useStyle
42
45
  } from "../../composables";
43
46
  const props = defineProps({
@@ -45,13 +48,32 @@ const props = defineProps({
45
48
  isValid: { type: [Boolean, null], required: false, default: null },
46
49
  disabled: { type: Boolean, required: false, default: false },
47
50
  readonly: { type: Boolean, required: false, default: false },
48
- error: { type: Boolean, required: false, default: false },
51
+ error: { type: [String, Boolean], required: false, default: false },
49
52
  inset: { type: Boolean, required: false, default: false },
50
53
  id: { type: String, required: false },
51
54
  class: { type: [String, Array, Object], required: false },
52
55
  style: { type: [String, Array, Object, Boolean, null], required: false, skipCheck: true },
53
56
  color: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
54
- bgColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true }
57
+ bgColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
58
+ border: { type: [Boolean, Number, String, Array], required: false, skipCheck: true },
59
+ borderTop: { type: [Boolean, Number, String], required: false },
60
+ borderLeft: { type: [Boolean, Number, String], required: false },
61
+ borderBottom: { type: [Boolean, Number, String], required: false },
62
+ borderRight: { type: [Boolean, Number, String], required: false },
63
+ borderBlock: { type: [Boolean, Number, String], required: false },
64
+ borderInline: { type: [Boolean, Number, String], required: false },
65
+ borderColor: { type: String, required: false },
66
+ borderStyle: { type: String, required: false },
67
+ borderTopColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
68
+ borderRightColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
69
+ borderBottomColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
70
+ borderLeftColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
71
+ rounded: { type: [Boolean, Number, String, null], required: false, skipCheck: true },
72
+ roundedTopRight: { type: [Boolean, Number, String], required: false },
73
+ roundedTopLeft: { type: [Boolean, Number, String], required: false },
74
+ roundedBottomLeft: { type: [Boolean, Number, String], required: false },
75
+ roundedBottomRight: { type: [Boolean, Number, String], required: false },
76
+ elevation: { type: [Number, String], required: false }
55
77
  });
56
78
  const emits = defineEmits(["click", "update:modelValue"]);
57
79
  defineSlots();
@@ -62,6 +84,9 @@ const trackBgColor = computed(() => {
62
84
  return props.bgColor;
63
85
  });
64
86
  const { backgroundColorStyles } = useBackgroundColor(trackBgColor);
87
+ const { borderClasses, borderStyles } = useBorder(props);
88
+ const { roundedClasses, roundedStyles } = useRounded(props);
89
+ const { elevationClasses, elevationStyles } = useElevation(props);
65
90
  const slotProps = computed(() => ({
66
91
  model: props.modelValue,
67
92
  isValid: props.isValid
@@ -75,6 +100,9 @@ const handleClick = (e) => {
75
100
  const switchTrackStyles = computed(() => {
76
101
  return [
77
102
  backgroundColorStyles.value,
103
+ borderStyles.value,
104
+ roundedStyles.value,
105
+ elevationStyles.value,
78
106
  props.style
79
107
  ];
80
108
  });
@@ -88,6 +116,9 @@ const switchTrackClasses = computed(() => {
88
116
  "origam-switch-track--error": props.error,
89
117
  "origam-switch-track--inset": props.inset
90
118
  },
119
+ borderClasses.value,
120
+ roundedClasses.value,
121
+ elevationClasses.value,
91
122
  props.class
92
123
  ];
93
124
  });
@@ -115,6 +146,8 @@ defineExpose({
115
146
  border-radius: var(--origam-switch__track---border-radius, 9999px);
116
147
  height: var(--origam-switch__track---height, 14px);
117
148
  min-width: var(--origam-switch__track---width, 36px);
149
+ backdrop-filter: var(--origam-switch__track---backdrop-filter, none);
150
+ -webkit-backdrop-filter: var(--origam-switch__track---backdrop-filter, none);
118
151
  cursor: pointer;
119
152
  transition: 0.2s background-color cubic-bezier(0.4, 0, 0.2, 1);
120
153
  overflow: hidden;