vuetify 3.5.11 → 3.5.12

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 (182) hide show
  1. package/dist/_component-variables-labs.sass +2 -1
  2. package/dist/json/attributes.json +243 -19
  3. package/dist/json/importMap-labs.json +22 -10
  4. package/dist/json/importMap.json +124 -124
  5. package/dist/json/tags.json +71 -0
  6. package/dist/json/web-types.json +747 -38
  7. package/dist/vuetify-labs.css +2339 -2089
  8. package/dist/vuetify-labs.d.ts +1117 -154
  9. package/dist/vuetify-labs.esm.js +675 -25
  10. package/dist/vuetify-labs.esm.js.map +1 -1
  11. package/dist/vuetify-labs.js +675 -25
  12. package/dist/vuetify-labs.min.css +2 -2
  13. package/dist/vuetify.css +1661 -1652
  14. package/dist/vuetify.d.ts +321 -192
  15. package/dist/vuetify.esm.js +33 -19
  16. package/dist/vuetify.esm.js.map +1 -1
  17. package/dist/vuetify.js +33 -19
  18. package/dist/vuetify.js.map +1 -1
  19. package/dist/vuetify.min.css +2 -2
  20. package/dist/vuetify.min.js +93 -92
  21. package/dist/vuetify.min.js.map +1 -1
  22. package/lib/components/VAvatar/VAvatar.css +6 -0
  23. package/lib/components/VAvatar/VAvatar.sass +6 -0
  24. package/lib/components/VAvatar/_variables.scss +2 -0
  25. package/lib/components/VCheckbox/index.d.mts +54 -18
  26. package/lib/components/VChip/VChip.css +5 -2
  27. package/lib/components/VChip/VChip.sass +3 -0
  28. package/lib/components/VChip/_variables.scss +2 -2
  29. package/lib/components/VDivider/VDivider.css +1 -1
  30. package/lib/components/VDivider/VDivider.sass +1 -1
  31. package/lib/components/VExpansionPanel/VExpansionPanel.css +3 -3
  32. package/lib/components/VExpansionPanel/VExpansionPanel.sass +2 -2
  33. package/lib/components/VField/VField.css +1 -1
  34. package/lib/components/VField/_variables.scss +1 -1
  35. package/lib/components/VFileInput/index.d.mts +12 -12
  36. package/lib/components/VForm/index.d.mts +42 -42
  37. package/lib/components/VInput/index.d.mts +6 -6
  38. package/lib/components/VRadio/index.d.mts +27 -9
  39. package/lib/components/VRadioGroup/index.d.mts +27 -9
  40. package/lib/components/VSelectionControl/VSelectionControl.mjs +1 -0
  41. package/lib/components/VSelectionControl/VSelectionControl.mjs.map +1 -1
  42. package/lib/components/VSelectionControl/index.d.mts +27 -9
  43. package/lib/components/VSelectionControlGroup/VSelectionControlGroup.mjs +1 -1
  44. package/lib/components/VSelectionControlGroup/VSelectionControlGroup.mjs.map +1 -1
  45. package/lib/components/VSelectionControlGroup/index.d.mts +27 -9
  46. package/lib/components/VSwitch/index.d.mts +27 -9
  47. package/lib/components/VTextField/index.d.mts +12 -12
  48. package/lib/components/VTextarea/index.d.mts +12 -12
  49. package/lib/components/VValidation/index.d.mts +6 -6
  50. package/lib/components/index.d.mts +279 -153
  51. package/lib/composables/form.mjs.map +1 -1
  52. package/lib/composables/router.mjs +16 -8
  53. package/lib/composables/router.mjs.map +1 -1
  54. package/lib/composables/transition.mjs +5 -2
  55. package/lib/composables/transition.mjs.map +1 -1
  56. package/lib/composables/validation.mjs +5 -4
  57. package/lib/composables/validation.mjs.map +1 -1
  58. package/lib/entry-bundler.mjs +1 -1
  59. package/lib/framework.mjs +1 -1
  60. package/lib/index.d.mts +42 -39
  61. package/lib/labs/VNumberInput/VNumberInput.mjs +4 -4
  62. package/lib/labs/VNumberInput/VNumberInput.mjs.map +1 -1
  63. package/lib/labs/VTimePicker/SelectingTimes.mjs.map +1 -0
  64. package/lib/labs/VTimePicker/VTimePicker.css +8 -0
  65. package/lib/labs/VTimePicker/VTimePicker.mjs +265 -0
  66. package/lib/labs/VTimePicker/VTimePicker.mjs.map +1 -0
  67. package/lib/labs/VTimePicker/VTimePicker.sass +10 -0
  68. package/lib/labs/VTimePicker/VTimePickerClock.css +130 -0
  69. package/lib/labs/VTimePicker/VTimePickerClock.mjs +244 -0
  70. package/lib/labs/VTimePicker/VTimePickerClock.mjs.map +1 -0
  71. package/lib/{components → labs}/VTimePicker/VTimePickerClock.sass +22 -39
  72. package/lib/labs/VTimePicker/VTimePickerControls.css +104 -0
  73. package/lib/labs/VTimePicker/VTimePickerControls.mjs +125 -0
  74. package/lib/labs/VTimePicker/VTimePickerControls.mjs.map +1 -0
  75. package/lib/labs/VTimePicker/VTimePickerControls.sass +102 -0
  76. package/lib/labs/VTimePicker/_variables.scss +34 -0
  77. package/lib/labs/VTimePicker/index.d.mts +848 -0
  78. package/lib/labs/VTimePicker/index.mjs +4 -0
  79. package/lib/labs/VTimePicker/index.mjs.map +1 -0
  80. package/lib/labs/components.d.mts +835 -1
  81. package/lib/labs/components.mjs +1 -0
  82. package/lib/labs/components.mjs.map +1 -1
  83. package/lib/locale/af.mjs +2 -1
  84. package/lib/locale/af.mjs.map +1 -1
  85. package/lib/locale/ar.mjs +2 -1
  86. package/lib/locale/ar.mjs.map +1 -1
  87. package/lib/locale/az.mjs +2 -1
  88. package/lib/locale/az.mjs.map +1 -1
  89. package/lib/locale/bg.mjs +2 -1
  90. package/lib/locale/bg.mjs.map +1 -1
  91. package/lib/locale/ca.mjs +2 -1
  92. package/lib/locale/ca.mjs.map +1 -1
  93. package/lib/locale/ckb.mjs +2 -1
  94. package/lib/locale/ckb.mjs.map +1 -1
  95. package/lib/locale/cs.mjs +2 -1
  96. package/lib/locale/cs.mjs.map +1 -1
  97. package/lib/locale/da.mjs +2 -1
  98. package/lib/locale/da.mjs.map +1 -1
  99. package/lib/locale/de.mjs +2 -1
  100. package/lib/locale/de.mjs.map +1 -1
  101. package/lib/locale/el.mjs +2 -1
  102. package/lib/locale/el.mjs.map +1 -1
  103. package/lib/locale/en.mjs +2 -1
  104. package/lib/locale/en.mjs.map +1 -1
  105. package/lib/locale/es.mjs +2 -1
  106. package/lib/locale/es.mjs.map +1 -1
  107. package/lib/locale/et.mjs +2 -1
  108. package/lib/locale/et.mjs.map +1 -1
  109. package/lib/locale/fa.mjs +2 -1
  110. package/lib/locale/fa.mjs.map +1 -1
  111. package/lib/locale/fi.mjs +2 -1
  112. package/lib/locale/fi.mjs.map +1 -1
  113. package/lib/locale/fr.mjs +2 -1
  114. package/lib/locale/fr.mjs.map +1 -1
  115. package/lib/locale/he.mjs +2 -1
  116. package/lib/locale/he.mjs.map +1 -1
  117. package/lib/locale/hr.mjs +2 -1
  118. package/lib/locale/hr.mjs.map +1 -1
  119. package/lib/locale/hu.mjs +2 -1
  120. package/lib/locale/hu.mjs.map +1 -1
  121. package/lib/locale/id.mjs +2 -1
  122. package/lib/locale/id.mjs.map +1 -1
  123. package/lib/locale/index.d.mts +43 -0
  124. package/lib/locale/it.mjs +2 -1
  125. package/lib/locale/it.mjs.map +1 -1
  126. package/lib/locale/ja.mjs +2 -1
  127. package/lib/locale/ja.mjs.map +1 -1
  128. package/lib/locale/km.mjs +2 -1
  129. package/lib/locale/km.mjs.map +1 -1
  130. package/lib/locale/ko.mjs +2 -1
  131. package/lib/locale/ko.mjs.map +1 -1
  132. package/lib/locale/lt.mjs +2 -1
  133. package/lib/locale/lt.mjs.map +1 -1
  134. package/lib/locale/lv.mjs +2 -1
  135. package/lib/locale/lv.mjs.map +1 -1
  136. package/lib/locale/nl.mjs +2 -1
  137. package/lib/locale/nl.mjs.map +1 -1
  138. package/lib/locale/no.mjs +2 -1
  139. package/lib/locale/no.mjs.map +1 -1
  140. package/lib/locale/pl.mjs +2 -1
  141. package/lib/locale/pl.mjs.map +1 -1
  142. package/lib/locale/pt.mjs +2 -1
  143. package/lib/locale/pt.mjs.map +1 -1
  144. package/lib/locale/ro.mjs +2 -1
  145. package/lib/locale/ro.mjs.map +1 -1
  146. package/lib/locale/ru.mjs +2 -1
  147. package/lib/locale/ru.mjs.map +1 -1
  148. package/lib/locale/sk.mjs +2 -1
  149. package/lib/locale/sk.mjs.map +1 -1
  150. package/lib/locale/sl.mjs +2 -1
  151. package/lib/locale/sl.mjs.map +1 -1
  152. package/lib/locale/sr-Cyrl.mjs +2 -1
  153. package/lib/locale/sr-Cyrl.mjs.map +1 -1
  154. package/lib/locale/sr-Latn.mjs +2 -1
  155. package/lib/locale/sr-Latn.mjs.map +1 -1
  156. package/lib/locale/sv.mjs +2 -1
  157. package/lib/locale/sv.mjs.map +1 -1
  158. package/lib/locale/th.mjs +2 -1
  159. package/lib/locale/th.mjs.map +1 -1
  160. package/lib/locale/tr.mjs +2 -1
  161. package/lib/locale/tr.mjs.map +1 -1
  162. package/lib/locale/uk.mjs +2 -1
  163. package/lib/locale/uk.mjs.map +1 -1
  164. package/lib/locale/vi.mjs +2 -1
  165. package/lib/locale/vi.mjs.map +1 -1
  166. package/lib/locale/zh-Hans.mjs +2 -1
  167. package/lib/locale/zh-Hans.mjs.map +1 -1
  168. package/lib/locale/zh-Hant.mjs +2 -1
  169. package/lib/locale/zh-Hant.mjs.map +1 -1
  170. package/package.json +4 -4
  171. package/lib/components/VTimePicker/SelectingTimes.mjs.map +0 -1
  172. package/lib/components/VTimePicker/VTimePicker.mjs +0 -288
  173. package/lib/components/VTimePicker/VTimePicker.mjs.map +0 -1
  174. package/lib/components/VTimePicker/VTimePickerClock.mjs +0 -251
  175. package/lib/components/VTimePicker/VTimePickerClock.mjs.map +0 -1
  176. package/lib/components/VTimePicker/VTimePickerTitle.mjs +0 -64
  177. package/lib/components/VTimePicker/VTimePickerTitle.mjs.map +0 -1
  178. package/lib/components/VTimePicker/VTimePickerTitle.sass +0 -61
  179. package/lib/components/VTimePicker/_variables.scss +0 -32
  180. package/lib/components/VTimePicker/index.mjs +0 -12
  181. package/lib/components/VTimePicker/index.mjs.map +0 -1
  182. /package/lib/{components → labs}/VTimePicker/SelectingTimes.mjs +0 -0
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.5.11
2
+ * Vuetify v3.5.12
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -317,7 +317,7 @@
317
317
  let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
318
318
  return str + char.repeat(Math.max(0, length - str.length));
319
319
  }
320
- function padStart(str, length) {
320
+ function padStart$1(str, length) {
321
321
  let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
322
322
  return char.repeat(Math.max(0, length - str.length)) + str;
323
323
  }
@@ -2011,7 +2011,8 @@
2011
2011
  },
2012
2012
  timePicker: {
2013
2013
  am: 'AM',
2014
- pm: 'PM'
2014
+ pm: 'PM',
2015
+ title: 'Select Time'
2015
2016
  },
2016
2017
  pagination: {
2017
2018
  ariaLabel: {
@@ -3173,10 +3174,13 @@
3173
3174
  } = typeof transition === 'object' ? transition : {};
3174
3175
  return vue.h(component, vue.mergeProps(typeof transition === 'string' ? {
3175
3176
  name: disabled ? '' : transition
3176
- } : customProps, typeof transition === 'string' ? {} : {
3177
+ } : customProps, typeof transition === 'string' ? {} : Object.fromEntries(Object.entries({
3177
3178
  disabled,
3178
3179
  group
3179
- }, rest), slots);
3180
+ }).filter(_ref2 => {
3181
+ let [_, v] = _ref2;
3182
+ return v !== undefined;
3183
+ })), rest), slots);
3180
3184
  };
3181
3185
 
3182
3186
  // Utilities
@@ -5087,19 +5091,27 @@
5087
5091
  href: vue.toRef(props, 'href')
5088
5092
  };
5089
5093
  }
5090
- const link = props.to ? RouterLink.useLink(props) : undefined;
5094
+ // vue-router useLink `to` prop needs to be reactive and useLink will crash if undefined
5095
+ const linkProps = vue.computed(() => ({
5096
+ ...props,
5097
+ to: props.to ? props.to : {}
5098
+ }));
5099
+ const routerLink = RouterLink.useLink(linkProps.value);
5100
+ // Actual link needs to be undefined when to prop is not used
5101
+ const link = vue.computed(() => props.to ? routerLink : undefined);
5091
5102
  const route = useRoute();
5092
5103
  return {
5093
5104
  isLink,
5094
5105
  isClickable,
5095
- route: link?.route,
5096
- navigate: link?.navigate,
5097
- isActive: link && vue.computed(() => {
5098
- if (!props.exact) return link.isActive?.value;
5099
- if (!route.value) return link.isExactActive?.value;
5100
- return link.isExactActive?.value && deepEqual(link.route.value.query, route.value.query);
5106
+ route: link.value?.route,
5107
+ navigate: link.value?.navigate,
5108
+ isActive: vue.computed(() => {
5109
+ if (!link.value) return false;
5110
+ if (!props.exact) return link.value.isActive?.value ?? false;
5111
+ if (!route.value) return link.value.isExactActive?.value ?? false;
5112
+ return link.value.isExactActive?.value && deepEqual(link.value.route.value.query, route.value.query);
5101
5113
  }),
5102
- href: vue.computed(() => props.to ? link?.route.value.href : props.href)
5114
+ href: vue.computed(() => props.to ? link.value?.route.value.href : props.href)
5103
5115
  };
5104
5116
  }
5105
5117
  const makeRouterProps = propsFactory({
@@ -5985,7 +5997,7 @@
5985
5997
  falseIcon: IconValue,
5986
5998
  trueIcon: IconValue,
5987
5999
  ripple: {
5988
- type: Boolean,
6000
+ type: [Boolean, Object],
5989
6001
  default: true
5990
6002
  },
5991
6003
  multiple: {
@@ -6209,6 +6221,7 @@
6209
6221
  "onFocus": onFocus,
6210
6222
  "onInput": onInput,
6211
6223
  "aria-disabled": !!props.disabled,
6224
+ "aria-label": props.label,
6212
6225
  "type": props.type,
6213
6226
  "value": trueValue.value,
6214
6227
  "name": props.name,
@@ -6668,14 +6681,15 @@
6668
6681
  vue.watch([isValid, errorMessages], () => {
6669
6682
  form?.update(uid.value, isValid.value, errorMessages.value);
6670
6683
  });
6671
- function reset() {
6684
+ async function reset() {
6672
6685
  model.value = null;
6673
- vue.nextTick(resetValidation);
6686
+ await vue.nextTick();
6687
+ await resetValidation();
6674
6688
  }
6675
- function resetValidation() {
6689
+ async function resetValidation() {
6676
6690
  isPristine.value = true;
6677
6691
  if (!validateOn.value.lazy) {
6678
- validate(true);
6692
+ await validate(true);
6679
6693
  } else {
6680
6694
  internalErrorMessages.value = [];
6681
6695
  }
@@ -17511,8 +17525,8 @@
17511
17525
  function toISO(adapter, value) {
17512
17526
  const date = adapter.toJsDate(value);
17513
17527
  const year = date.getFullYear();
17514
- const month = padStart(String(date.getMonth() + 1), 2, '0');
17515
- const day = padStart(String(date.getDate()), 2, '0');
17528
+ const month = padStart$1(String(date.getMonth() + 1), 2, '0');
17529
+ const day = padStart$1(String(date.getDate()), 2, '0');
17516
17530
  return `${year}-${month}-${day}`;
17517
17531
  }
17518
17532
  function parseISO(value) {
@@ -26569,17 +26583,17 @@
26569
26583
  ...slotProps
26570
26584
  }
26571
26585
  } = _ref2;
26572
- return vue.createVNode("input", vue.mergeProps({
26586
+ return vue.withDirectives(vue.createVNode("input", vue.mergeProps({
26573
26587
  "ref": inputRef,
26574
26588
  "type": "number",
26575
- "value": model.value,
26589
+ "onUpdate:modelValue": $event => model.value = $event,
26576
26590
  "class": fieldClass,
26577
26591
  "max": props.max,
26578
26592
  "min": props.min,
26579
26593
  "step": props.step,
26580
26594
  "onFocus": onFocus,
26581
26595
  "onBlur": blur
26582
- }, inputAttrs), null);
26596
+ }, inputAttrs), null), [[vue.vModelText, model.value]]);
26583
26597
  },
26584
26598
  'append-inner': controlVariant.value === 'split' ? () => vue.createVNode("div", {
26585
26599
  "class": "v-number-input__control"
@@ -27109,6 +27123,639 @@
27109
27123
 
27110
27124
  // Types
27111
27125
 
27126
+ const makeVTimePickerClockProps = propsFactory({
27127
+ allowedValues: Function,
27128
+ ampm: Boolean,
27129
+ color: String,
27130
+ disabled: Boolean,
27131
+ displayedValue: {
27132
+ default: null
27133
+ },
27134
+ double: Boolean,
27135
+ format: {
27136
+ type: Function,
27137
+ default: val => val
27138
+ },
27139
+ max: {
27140
+ type: Number,
27141
+ required: true
27142
+ },
27143
+ min: {
27144
+ type: Number,
27145
+ required: true
27146
+ },
27147
+ scrollable: Boolean,
27148
+ readonly: Boolean,
27149
+ rotate: {
27150
+ type: Number,
27151
+ default: 0
27152
+ },
27153
+ step: {
27154
+ type: Number,
27155
+ default: 1
27156
+ },
27157
+ modelValue: {
27158
+ type: Number
27159
+ }
27160
+ }, 'VTimePickerClock');
27161
+ const VTimePickerClock = genericComponent()({
27162
+ name: 'VTimePickerClock',
27163
+ props: makeVTimePickerClockProps(),
27164
+ emits: {
27165
+ change: val => val,
27166
+ input: val => val
27167
+ },
27168
+ setup(props, _ref) {
27169
+ let {
27170
+ emit
27171
+ } = _ref;
27172
+ const clockRef = vue.ref(null);
27173
+ const innerClockRef = vue.ref(null);
27174
+ const inputValue = vue.ref(undefined);
27175
+ const isDragging = vue.ref(false);
27176
+ const valueOnMouseDown = vue.ref(null);
27177
+ const valueOnMouseUp = vue.ref(null);
27178
+ const {
27179
+ textColorClasses,
27180
+ textColorStyles
27181
+ } = useTextColor(vue.toRef(props, 'color'));
27182
+ const {
27183
+ backgroundColorClasses,
27184
+ backgroundColorStyles
27185
+ } = useBackgroundColor(vue.toRef(props, 'color'));
27186
+ const count = vue.computed(() => props.max - props.min + 1);
27187
+ const roundCount = vue.computed(() => props.double ? count.value / 2 : count.value);
27188
+ const degreesPerUnit = vue.computed(() => 360 / roundCount.value);
27189
+ const degrees = vue.computed(() => degreesPerUnit.value * Math.PI / 180);
27190
+ const displayedValue = vue.computed(() => props.modelValue == null ? props.min : props.modelValue);
27191
+ const innerRadiusScale = vue.computed(() => 0.62);
27192
+ const genChildren = vue.computed(() => {
27193
+ const children = [];
27194
+ for (let value = props.min; value <= props.max; value = value + props.step) {
27195
+ children.push(value);
27196
+ }
27197
+ return children;
27198
+ });
27199
+ vue.watch(() => props.modelValue, val => {
27200
+ inputValue.value = val;
27201
+ });
27202
+ function update(value) {
27203
+ if (inputValue.value !== value) {
27204
+ inputValue.value = value;
27205
+ }
27206
+ emit('input', value);
27207
+ }
27208
+ function isAllowed(value) {
27209
+ return !props.allowedValues || props.allowedValues(value);
27210
+ }
27211
+ function wheel(e) {
27212
+ e.preventDefault();
27213
+ const delta = Math.sign(-e.deltaY || 1);
27214
+ let value = displayedValue.value;
27215
+ do {
27216
+ value = value + delta;
27217
+ value = (value - props.min + count.value) % count.value + props.min;
27218
+ } while (!isAllowed(value) && value !== displayedValue.value);
27219
+ if (value !== props.displayedValue) {
27220
+ update(value);
27221
+ }
27222
+ }
27223
+ function isInner(value) {
27224
+ return props.double && value - props.min >= roundCount.value;
27225
+ }
27226
+ function handScale(value) {
27227
+ return isInner(value) ? innerRadiusScale.value : 1;
27228
+ }
27229
+ function getPosition(value) {
27230
+ const rotateRadians = props.rotate * Math.PI / 180;
27231
+ return {
27232
+ x: Math.sin((value - props.min) * degrees.value + rotateRadians) * handScale(value),
27233
+ y: -Math.cos((value - props.min) * degrees.value + rotateRadians) * handScale(value)
27234
+ };
27235
+ }
27236
+ function angleToValue(angle, insideClick) {
27237
+ const value = (Math.round(angle / degreesPerUnit.value) + (insideClick ? roundCount.value : 0)) % count.value + props.min;
27238
+
27239
+ // Necessary to fix edge case when selecting left part of the value(s) at 12 o'clock
27240
+ if (angle < 360 - degreesPerUnit.value / 2) return value;
27241
+ return insideClick ? props.max - roundCount.value + 1 : props.min;
27242
+ }
27243
+ function getTransform(i) {
27244
+ const {
27245
+ x,
27246
+ y
27247
+ } = getPosition(i);
27248
+ return {
27249
+ left: `${50 + x * 50}%`,
27250
+ top: `${50 + y * 50}%`
27251
+ };
27252
+ }
27253
+ function euclidean(p0, p1) {
27254
+ const dx = p1.x - p0.x;
27255
+ const dy = p1.y - p0.y;
27256
+ return Math.sqrt(dx * dx + dy * dy);
27257
+ }
27258
+ function angle(center, p1) {
27259
+ const value = 2 * Math.atan2(p1.y - center.y - euclidean(center, p1), p1.x - center.x);
27260
+ return Math.abs(value * 180 / Math.PI);
27261
+ }
27262
+ function setMouseDownValue(value) {
27263
+ if (valueOnMouseDown.value === null) {
27264
+ valueOnMouseDown.value = value;
27265
+ }
27266
+ valueOnMouseUp.value = value;
27267
+ update(value);
27268
+ }
27269
+ function onDragMove(e) {
27270
+ e.preventDefault();
27271
+ if (!isDragging.value && e.type !== 'click' || !clockRef.value) return;
27272
+ const {
27273
+ width,
27274
+ top,
27275
+ left
27276
+ } = clockRef.value?.getBoundingClientRect();
27277
+ const {
27278
+ width: innerWidth
27279
+ } = innerClockRef.value?.getBoundingClientRect() ?? {
27280
+ width: 0
27281
+ };
27282
+ const {
27283
+ clientX,
27284
+ clientY
27285
+ } = 'touches' in e ? e.touches[0] : e;
27286
+ const center = {
27287
+ x: width / 2,
27288
+ y: -width / 2
27289
+ };
27290
+ const coords = {
27291
+ x: clientX - left,
27292
+ y: top - clientY
27293
+ };
27294
+ const handAngle = Math.round(angle(center, coords) - props.rotate + 360) % 360;
27295
+ const insideClick = props.double && euclidean(center, coords) < (innerWidth + innerWidth * innerRadiusScale.value) / 4;
27296
+ const checksCount = Math.ceil(15 / degreesPerUnit.value);
27297
+ let value;
27298
+ for (let i = 0; i < checksCount; i++) {
27299
+ value = angleToValue(handAngle + i * degreesPerUnit.value, insideClick);
27300
+ if (isAllowed(value)) return setMouseDownValue(value);
27301
+ value = angleToValue(handAngle - i * degreesPerUnit.value, insideClick);
27302
+ if (isAllowed(value)) return setMouseDownValue(value);
27303
+ }
27304
+ }
27305
+ function onMouseDown(e) {
27306
+ e.preventDefault();
27307
+ valueOnMouseDown.value = null;
27308
+ valueOnMouseUp.value = null;
27309
+ isDragging.value = true;
27310
+ onDragMove(e);
27311
+ }
27312
+ function onMouseUp(e) {
27313
+ e.stopPropagation();
27314
+ isDragging.value = false;
27315
+ if (valueOnMouseUp.value !== null && isAllowed(valueOnMouseUp.value)) {
27316
+ emit('change', valueOnMouseUp.value);
27317
+ }
27318
+ }
27319
+ useRender(() => {
27320
+ return vue.createVNode("div", {
27321
+ "class": [{
27322
+ 'v-time-picker-clock': true,
27323
+ 'v-time-picker-clock--indeterminate': props.modelValue == null,
27324
+ 'v-time-picker-clock--readonly': props.readonly
27325
+ }],
27326
+ "onMousedown": onMouseDown,
27327
+ "onMouseup": onMouseUp,
27328
+ "onMouseleave": e => isDragging.value && onMouseUp(e),
27329
+ "onTouchstart": onMouseDown,
27330
+ "onTouchend": onMouseUp,
27331
+ "onMousemove": onDragMove,
27332
+ "onTouchmove": onDragMove,
27333
+ "onWheel": e => props.scrollable && wheel(e),
27334
+ "ref": clockRef
27335
+ }, [vue.createVNode("div", {
27336
+ "class": "v-time-picker-clock__inner",
27337
+ "ref": innerClockRef
27338
+ }, [vue.createVNode("div", {
27339
+ "class": [{
27340
+ 'v-time-picker-clock__hand': true,
27341
+ 'v-time-picker-clock__hand--inner': isInner(props.modelValue)
27342
+ }, textColorClasses.value],
27343
+ "style": [{
27344
+ transform: `rotate(${props.rotate + degreesPerUnit.value * (displayedValue.value - props.min)}deg) scaleY(${handScale(displayedValue.value)})`
27345
+ }, textColorStyles.value]
27346
+ }, null), genChildren.value.map(value => {
27347
+ const isActive = value === displayedValue.value;
27348
+ return vue.createVNode("div", {
27349
+ "class": [{
27350
+ 'v-time-picker-clock__item': true,
27351
+ 'v-time-picker-clock__item--active': isActive,
27352
+ 'v-time-picker-clock__item--disabled': props.disabled || !isAllowed(value)
27353
+ }, isActive && backgroundColorClasses.value],
27354
+ "style": [getTransform(value), isActive && backgroundColorStyles.value]
27355
+ }, [vue.createVNode("span", null, [props.format(value)])]);
27356
+ })])]);
27357
+ });
27358
+ }
27359
+ });
27360
+
27361
+ // @ts-nocheck
27362
+ /* eslint-disable */
27363
+
27364
+ const padStart = (string, targetLength, padString) => {
27365
+ targetLength = targetLength >> 0;
27366
+ string = String(string);
27367
+ padString = String(padString);
27368
+ if (string.length > targetLength) {
27369
+ return String(string);
27370
+ }
27371
+ targetLength = targetLength - string.length;
27372
+ if (targetLength > padString.length) {
27373
+ padString += padString.repeat(targetLength / padString.length);
27374
+ }
27375
+ return padString.slice(0, targetLength) + String(string);
27376
+ };
27377
+ var pad = (function (n) {
27378
+ let length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
27379
+ return padStart(n, length, '0');
27380
+ });
27381
+
27382
+ // @ts-nocheck
27383
+ /* eslint-disable */
27384
+ var SelectingTimes = /*#__PURE__*/function (SelectingTimes) {
27385
+ SelectingTimes[SelectingTimes["Hour"] = 1] = "Hour";
27386
+ SelectingTimes[SelectingTimes["Minute"] = 2] = "Minute";
27387
+ SelectingTimes[SelectingTimes["Second"] = 3] = "Second";
27388
+ return SelectingTimes;
27389
+ }(SelectingTimes || {});
27390
+
27391
+ const makeVTimePickerControlsProps = propsFactory({
27392
+ ampm: Boolean,
27393
+ ampmReadonly: Boolean,
27394
+ color: String,
27395
+ disabled: Boolean,
27396
+ hour: Number,
27397
+ minute: Number,
27398
+ second: Number,
27399
+ period: String,
27400
+ readonly: Boolean,
27401
+ useSeconds: Boolean,
27402
+ selecting: Number,
27403
+ value: Number
27404
+ }, 'VTimePickerControls');
27405
+ const VTimePickerControls = genericComponent()({
27406
+ name: 'VTimePickerControls',
27407
+ props: makeVTimePickerControlsProps(),
27408
+ emits: {
27409
+ 'update:period': data => data,
27410
+ 'update:selecting': data => data
27411
+ },
27412
+ setup(props, _ref) {
27413
+ let {
27414
+ emit,
27415
+ slots
27416
+ } = _ref;
27417
+ const {
27418
+ t
27419
+ } = useLocale();
27420
+ useRender(() => {
27421
+ let hour = props.hour;
27422
+ if (props.ampm) {
27423
+ hour = hour ? (hour - 1) % 12 + 1 : 12;
27424
+ }
27425
+ return vue.createVNode("div", {
27426
+ "class": "v-time-picker-controls"
27427
+ }, [vue.createVNode("div", {
27428
+ "class": {
27429
+ 'v-time-picker-controls__time': true,
27430
+ 'v-time-picker-controls__time--with-seconds': props.useSeconds
27431
+ }
27432
+ }, [vue.createVNode(VBtn, {
27433
+ "active": props.selecting === 1,
27434
+ "color": props.selecting === 1 ? props.color : undefined,
27435
+ "variant": "tonal",
27436
+ "class": {
27437
+ 'v-time-picker-controls__time__btn': true,
27438
+ 'v-time-picker-controls__time--with-ampm__btn': props.ampm,
27439
+ 'v-time-picker-controls__time--with-seconds__btn': props.useSeconds
27440
+ },
27441
+ "text": props.hour == null ? '--' : pad(`${hour}`),
27442
+ "onClick": () => emit('update:selecting', SelectingTimes.Hour)
27443
+ }, null), vue.createVNode("span", {
27444
+ "class": ['v-time-picker-controls__time__separator', {
27445
+ 'v-time-picker-controls--with-seconds__time__separator': props.useSeconds
27446
+ }]
27447
+ }, [vue.createTextVNode(":")]), vue.createVNode(VBtn, {
27448
+ "active": props.selecting === 2,
27449
+ "color": props.selecting === 2 ? props.color : undefined,
27450
+ "class": {
27451
+ 'v-time-picker-controls__time__btn': true,
27452
+ 'v-time-picker-controls__time__btn__active': props.selecting === 2,
27453
+ 'v-time-picker-controls__time--with-ampm__btn': props.ampm,
27454
+ 'v-time-picker-controls__time--with-seconds__btn': props.useSeconds
27455
+ },
27456
+ "variant": "tonal",
27457
+ "text": props.minute == null ? '--' : pad(props.minute),
27458
+ "onClick": () => emit('update:selecting', SelectingTimes.Minute)
27459
+ }, null), props.useSeconds && vue.createVNode("span", {
27460
+ "class": ['v-time-picker-controls__time__separator', {
27461
+ 'v-time-picker-controls--with-seconds__time__separator': props.useSeconds
27462
+ }],
27463
+ "key": "secondsDivider"
27464
+ }, [vue.createTextVNode(":")]), props.useSeconds && vue.createVNode(VBtn, {
27465
+ "key": "secondsVal",
27466
+ "variant": "tonal",
27467
+ "onClick": () => emit('update:selecting', SelectingTimes.Second),
27468
+ "class": {
27469
+ 'v-time-picker-controls__time__btn': true,
27470
+ 'v-time-picker-controls__time__btn__active': props.selecting === 3,
27471
+ 'v-time-picker-controls__time--with-seconds__btn': props.useSeconds
27472
+ },
27473
+ "text": props.second == null ? '--' : pad(props.second)
27474
+ }, null), props.ampm && vue.createVNode("div", {
27475
+ "class": ['v-time-picker-controls__ampm', {
27476
+ 'v-time-picker-controls__ampm--readonly': props.ampmReadonly
27477
+ }]
27478
+ }, [vue.createVNode(VBtn, {
27479
+ "active": props.period === 'am',
27480
+ "color": props.period === 'am' ? props.color : undefined,
27481
+ "class": {
27482
+ 'v-time-picker-controls__ampm__am': true,
27483
+ 'v-time-picker-controls__ampm__btn': true,
27484
+ 'v-time-picker-controls__ampm__btn__active': props.period === 'am'
27485
+ },
27486
+ "text": t('$vuetify.timePicker.am'),
27487
+ "variant": "tonal",
27488
+ "onClick": () => props.period !== 'am' ? emit('update:period', 'am') : null
27489
+ }, null), vue.createVNode(VBtn, {
27490
+ "active": props.period === 'pm',
27491
+ "color": props.period === 'pm' ? props.color : undefined,
27492
+ "class": {
27493
+ 'v-time-picker-controls__ampm__pm': true,
27494
+ 'v-time-picker-controls__ampm__btn': true,
27495
+ 'v-time-picker-controls__ampm__btn__active': props.period === 'pm'
27496
+ },
27497
+ "text": t('$vuetify.timePicker.pm'),
27498
+ "variant": "tonal",
27499
+ "onClick": () => props.period !== 'pm' ? emit('update:period', 'pm') : null
27500
+ }, null)])])]);
27501
+ });
27502
+ return {};
27503
+ }
27504
+ });
27505
+
27506
+ // Types
27507
+
27508
+ const rangeHours24 = createRange(24);
27509
+ const rangeHours12am = createRange(12);
27510
+ const rangeHours12pm = rangeHours12am.map(v => v + 12);
27511
+ const range60 = createRange(60);
27512
+ const selectingNames = {
27513
+ 1: 'hour',
27514
+ 2: 'minute',
27515
+ 3: 'second'
27516
+ };
27517
+ const makeVTimePickerProps = propsFactory({
27518
+ allowedHours: [Function, Array],
27519
+ allowedMinutes: [Function, Array],
27520
+ allowedSeconds: [Function, Array],
27521
+ ampmInTitle: Boolean,
27522
+ disabled: Boolean,
27523
+ format: {
27524
+ type: String,
27525
+ default: 'ampm'
27526
+ },
27527
+ max: String,
27528
+ min: String,
27529
+ modelValue: null,
27530
+ readonly: Boolean,
27531
+ scrollable: Boolean,
27532
+ useSeconds: Boolean,
27533
+ ...omit(makeVPickerProps({
27534
+ title: '$vuetify.timePicker.title'
27535
+ }), ['landscape'])
27536
+ }, 'VTimePicker');
27537
+ const VTimePicker = genericComponent()({
27538
+ name: 'VTimePicker',
27539
+ props: makeVTimePickerProps(),
27540
+ emits: {
27541
+ 'update:hour': val => val,
27542
+ 'update:minute': val => val,
27543
+ 'update:period': val => val,
27544
+ 'update:second': val => val,
27545
+ 'update:modelValue': val => val
27546
+ },
27547
+ setup(props, _ref) {
27548
+ let {
27549
+ emit,
27550
+ slots
27551
+ } = _ref;
27552
+ const {
27553
+ t
27554
+ } = useLocale();
27555
+ const inputHour = vue.ref(null);
27556
+ const inputMinute = vue.ref(null);
27557
+ const inputSecond = vue.ref(null);
27558
+ const lazyInputHour = vue.ref(null);
27559
+ const lazyInputMinute = vue.ref(null);
27560
+ const lazyInputSecond = vue.ref(null);
27561
+ const period = vue.ref('am');
27562
+ const selecting = vue.ref(SelectingTimes.Hour);
27563
+ const controlsRef = vue.ref(null);
27564
+ const clockRef = vue.ref(null);
27565
+ const isAllowedHourCb = vue.computed(() => {
27566
+ let cb;
27567
+ if (props.allowedHours instanceof Array) {
27568
+ cb = val => props.allowedHours.includes(val);
27569
+ } else {
27570
+ cb = props.allowedHours;
27571
+ }
27572
+ if (!props.min && !props.max) return cb;
27573
+ const minHour = props.min ? Number(props.min.split(':')[0]) : 0;
27574
+ const maxHour = props.max ? Number(props.max.split(':')[0]) : 23;
27575
+ return val => {
27576
+ return val >= minHour * 1 && val <= maxHour * 1 && (!cb || cb(val));
27577
+ };
27578
+ });
27579
+ const isAllowedMinuteCb = vue.computed(() => {
27580
+ let cb;
27581
+ const isHourAllowed = !isAllowedHourCb.value || inputHour.value === null || isAllowedHourCb.value(inputHour.value);
27582
+ if (props.allowedMinutes instanceof Array) {
27583
+ cb = val => props.allowedMinutes.includes(val);
27584
+ } else {
27585
+ cb = props.allowedMinutes;
27586
+ }
27587
+ if (!props.min && !props.max) {
27588
+ return isHourAllowed ? cb : () => false;
27589
+ }
27590
+ const [minHour, minMinute] = props.min ? props.min.split(':').map(Number) : [0, 0];
27591
+ const [maxHour, maxMinute] = props.max ? props.max.split(':').map(Number) : [23, 59];
27592
+ const minTime = minHour * 60 + minMinute * 1;
27593
+ const maxTime = maxHour * 60 + maxMinute * 1;
27594
+ return val => {
27595
+ const time = 60 * inputHour.value + val;
27596
+ return time >= minTime && time <= maxTime && isHourAllowed && (!cb || cb(val));
27597
+ };
27598
+ });
27599
+ const isAllowedSecondCb = vue.computed(() => {
27600
+ let cb;
27601
+ const isHourAllowed = !isAllowedHourCb.value || inputHour.value === null || isAllowedHourCb.value(inputHour.value);
27602
+ const isMinuteAllowed = isHourAllowed && (!isAllowedMinuteCb.value || inputMinute.value === null || isAllowedMinuteCb.value(inputMinute.value));
27603
+ if (props.allowedSeconds instanceof Array) {
27604
+ cb = val => props.allowedSeconds.includes(val);
27605
+ } else {
27606
+ cb = props.allowedSeconds;
27607
+ }
27608
+ if (!props.min && !props.max) {
27609
+ return isMinuteAllowed ? cb : () => false;
27610
+ }
27611
+ const [minHour, minMinute, minSecond] = props.min ? props.min.split(':').map(Number) : [0, 0, 0];
27612
+ const [maxHour, maxMinute, maxSecond] = props.max ? props.max.split(':').map(Number) : [23, 59, 59];
27613
+ const minTime = minHour * 3600 + minMinute * 60 + (minSecond || 0) * 1;
27614
+ const maxTime = maxHour * 3600 + maxMinute * 60 + (maxSecond || 0) * 1;
27615
+ return val => {
27616
+ const time = 3600 * inputHour.value + 60 * inputMinute.value + val;
27617
+ return time >= minTime && time <= maxTime && isMinuteAllowed && (!cb || cb(val));
27618
+ };
27619
+ });
27620
+ const isAmPm = vue.computed(() => {
27621
+ return props.format === 'ampm';
27622
+ });
27623
+ vue.watch(() => props.modelValue, val => setInputData(val));
27624
+ vue.onMounted(() => {
27625
+ setInputData(props.modelValue);
27626
+ });
27627
+ function genValue() {
27628
+ if (inputHour.value != null && inputMinute.value != null && (!props.useSeconds || inputSecond.value != null)) {
27629
+ return `${pad(inputHour.value)}:${pad(inputMinute.value)}` + (props.useSeconds ? `:${pad(inputSecond.value)}` : '');
27630
+ }
27631
+ return null;
27632
+ }
27633
+ function emitValue() {
27634
+ const value = genValue();
27635
+ if (value !== null) emit('update:modelValue', value);
27636
+ }
27637
+ function convert24to12(hour) {
27638
+ return hour ? (hour - 1) % 12 + 1 : 12;
27639
+ }
27640
+ function convert12to24(hour, period) {
27641
+ return hour % 12 + (period === 'pm' ? 12 : 0);
27642
+ }
27643
+ function setInputData(value) {
27644
+ if (value == null || value === '') {
27645
+ inputHour.value = null;
27646
+ inputMinute.value = null;
27647
+ inputSecond.value = null;
27648
+ } else if (value instanceof Date) {
27649
+ inputHour.value = value.getHours();
27650
+ inputMinute.value = value.getMinutes();
27651
+ inputSecond.value = value.getSeconds();
27652
+ } else {
27653
+ const [hour,, minute,, second, period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:(\d+))?([ap]m)?$/) || new Array(6);
27654
+ inputHour.value = period ? convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10);
27655
+ inputMinute.value = parseInt(minute, 10);
27656
+ inputSecond.value = parseInt(second || 0, 10);
27657
+ }
27658
+ period.value = inputHour.value == null || inputHour.value < 12 ? 'am' : 'pm';
27659
+ }
27660
+ function firstAllowed(type, value) {
27661
+ const allowedFn = type === 'hour' ? isAllowedHourCb.value : type === 'minute' ? isAllowedMinuteCb.value : isAllowedSecondCb.value;
27662
+ if (!allowedFn) return value;
27663
+
27664
+ // TODO: clean up (Note from V2 code)
27665
+ const range = type === 'minute' ? range60 : type === 'second' ? range60 : isAmPm.value ? value < 12 ? rangeHours12am : rangeHours12pm : rangeHours24;
27666
+ const first = range.find(v => allowedFn((v + value) % range.length + range[0]));
27667
+ return ((first || 0) + value) % range.length + range[0];
27668
+ }
27669
+ function setPeriod(val) {
27670
+ period.value = val;
27671
+ if (inputHour.value != null) {
27672
+ const newHour = inputHour.value + (period.value === 'am' ? -12 : 12);
27673
+ inputHour.value = firstAllowed('hour', newHour);
27674
+ }
27675
+ emit('update:period', val);
27676
+ emitValue();
27677
+ return true;
27678
+ }
27679
+ function onInput(value) {
27680
+ if (selecting.value === SelectingTimes.Hour) {
27681
+ inputHour.value = isAmPm.value ? convert12to24(value, period.value) : value;
27682
+ } else if (selecting.value === SelectingTimes.Minute) {
27683
+ inputMinute.value = value;
27684
+ } else {
27685
+ inputSecond.value = value;
27686
+ }
27687
+ }
27688
+ function onChange(value) {
27689
+ switch (selectingNames[selecting.value]) {
27690
+ case 'hour':
27691
+ emit('update:hour', value);
27692
+ break;
27693
+ case 'minutes':
27694
+ emit('update:minute', value);
27695
+ break;
27696
+ case 'seconds':
27697
+ emit('update:second', value);
27698
+ break;
27699
+ }
27700
+ const emitChange = selecting.value === (props.useSeconds ? SelectingTimes.Second : SelectingTimes.Minute);
27701
+ if (selecting.value === SelectingTimes.Hour) {
27702
+ selecting.value = SelectingTimes.Minute;
27703
+ } else if (props.useSeconds && selecting.value === SelectingTimes.Minute) {
27704
+ selecting.value = SelectingTimes.Second;
27705
+ }
27706
+ if (inputHour.value === lazyInputHour.value && inputMinute.value === lazyInputMinute.value && (!props.useSeconds || inputSecond.value === lazyInputSecond.value)) return;
27707
+ const time = genValue();
27708
+ if (time === null) return;
27709
+ lazyInputHour.value = inputHour.value;
27710
+ lazyInputMinute.value = inputMinute.value;
27711
+ props.useSeconds && (lazyInputSecond.value = inputSecond.value);
27712
+ emitChange && emitValue();
27713
+ }
27714
+ useRender(() => {
27715
+ const pickerProps = VPicker.filterProps(props);
27716
+ const timePickerControlsProps = VTimePickerControls.filterProps(props);
27717
+ const timePickerClockProps = VTimePickerClock.filterProps(omit(props, ['format', 'modelValue', 'min', 'max']));
27718
+ return vue.createVNode(VPicker, vue.mergeProps(pickerProps, {
27719
+ "color": undefined,
27720
+ "class": ['v-time-picker', props.class],
27721
+ "style": props.style
27722
+ }), {
27723
+ title: () => slots.title?.() ?? vue.createVNode("div", {
27724
+ "class": "v-time-picker__title"
27725
+ }, [t(props.title)]),
27726
+ header: () => vue.createVNode(VTimePickerControls, vue.mergeProps(timePickerControlsProps, {
27727
+ "ampm": isAmPm.value || props.ampmInTitle,
27728
+ "ampmReadonly": isAmPm.value && !props.ampmInTitle,
27729
+ "hour": inputHour.value,
27730
+ "minute": inputMinute.value,
27731
+ "period": period.value,
27732
+ "second": inputSecond.value,
27733
+ "selecting": selecting.value,
27734
+ "onUpdate:period": val => setPeriod(val),
27735
+ "onUpdate:selecting": value => selecting.value = value,
27736
+ "ref": controlsRef
27737
+ }), null),
27738
+ default: () => vue.createVNode(VTimePickerClock, vue.mergeProps(timePickerClockProps, {
27739
+ "allowedValues": selecting.value === SelectingTimes.Hour ? isAllowedHourCb.value : selecting.value === SelectingTimes.Minute ? isAllowedMinuteCb.value : isAllowedSecondCb.value,
27740
+ "double": selecting.value === SelectingTimes.Hour && !isAmPm.value,
27741
+ "format": selecting.value === SelectingTimes.Hour ? isAmPm.value ? convert24to12 : val => val : val => pad(val, 2),
27742
+ "max": selecting.value === SelectingTimes.Hour ? isAmPm.value && period.value === 'am' ? 11 : 23 : 59,
27743
+ "min": selecting.value === SelectingTimes.Hour && isAmPm.value && period.value === 'pm' ? 12 : 0,
27744
+ "size": 20,
27745
+ "step": selecting.value === SelectingTimes.Hour ? 1 : 5,
27746
+ "modelValue": selecting.value === SelectingTimes.Hour ? inputHour.value : selecting.value === SelectingTimes.Minute ? inputMinute.value : inputSecond.value,
27747
+ "onChange": onChange,
27748
+ "onInput": onInput,
27749
+ "ref": clockRef
27750
+ }), null),
27751
+ actions: slots.actions
27752
+ });
27753
+ });
27754
+ }
27755
+ });
27756
+
27757
+ // Types
27758
+
27112
27759
  const makeVTreeviewGroupProps = propsFactory({
27113
27760
  ...omit(makeVListGroupProps({
27114
27761
  collapseIcon: '$treeviewCollapse',
@@ -27627,6 +28274,9 @@
27627
28274
  VTextField: VTextField,
27628
28275
  VTextarea: VTextarea,
27629
28276
  VThemeProvider: VThemeProvider,
28277
+ VTimePicker: VTimePicker,
28278
+ VTimePickerClock: VTimePickerClock,
28279
+ VTimePickerControls: VTimePickerControls,
27630
28280
  VTimeline: VTimeline,
27631
28281
  VTimelineItem: VTimelineItem,
27632
28282
  VToolbar: VToolbar,
@@ -27862,7 +28512,7 @@
27862
28512
  goTo
27863
28513
  };
27864
28514
  }
27865
- const version$1 = "3.5.11";
28515
+ const version$1 = "3.5.12";
27866
28516
  createVuetify$1.version = version$1;
27867
28517
 
27868
28518
  // Vue's inject() can only be used in setup
@@ -28115,7 +28765,7 @@
28115
28765
 
28116
28766
  /* eslint-disable local-rules/sort-imports */
28117
28767
 
28118
- const version = "3.5.11";
28768
+ const version = "3.5.12";
28119
28769
 
28120
28770
  /* eslint-disable local-rules/sort-imports */
28121
28771