@dumiflex/wp-kit 0.3.0 → 0.4.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/CHANGELOG.md +77 -51
  2. package/LICENSE +674 -674
  3. package/README.md +73 -76
  4. package/package.json +78 -77
  5. package/src/Avatar.vue +83 -83
  6. package/src/Badge.vue +97 -97
  7. package/src/Banner.vue +118 -118
  8. package/src/BookmarkButton.vue +27 -27
  9. package/src/BundleMeta.vue +51 -51
  10. package/src/Button.vue +103 -103
  11. package/src/Card.vue +68 -68
  12. package/src/Checkbox.vue +109 -107
  13. package/src/Chip.vue +163 -97
  14. package/src/ChoiceCards.vue +133 -133
  15. package/src/CloseButton.vue +69 -69
  16. package/src/CodeBlock.vue +119 -119
  17. package/src/ColorField.vue +188 -206
  18. package/src/ColorPicker.vue +201 -201
  19. package/src/Combobox.vue +331 -334
  20. package/src/ConfirmDialog.vue +165 -163
  21. package/src/ConfirmModal.vue +147 -147
  22. package/src/ConstraintMatrixPreview.vue +708 -708
  23. package/src/ContextMenu.vue +386 -379
  24. package/src/CopyButton.vue +156 -156
  25. package/src/DataTable.vue +292 -292
  26. package/src/DatePicker.vue +234 -234
  27. package/src/DescriptionList.vue +73 -73
  28. package/src/DiffView.vue +68 -68
  29. package/src/Disclosure.vue +166 -166
  30. package/src/DragHandle.vue +49 -49
  31. package/src/Drawer.vue +131 -131
  32. package/src/DropZone.vue +196 -196
  33. package/src/DropdownMenu.vue +72 -72
  34. package/src/EmptyState.vue +111 -111
  35. package/src/Field.vue +28 -28
  36. package/src/HsvPicker.vue +208 -208
  37. package/src/Icon.vue +39 -39
  38. package/src/IconPicker.vue +209 -209
  39. package/src/ImageGrid.vue +125 -125
  40. package/src/InlineEdit.vue +183 -183
  41. package/src/Input.vue +99 -99
  42. package/src/Kbd.vue +56 -56
  43. package/src/Lightbox.vue +173 -173
  44. package/src/ListFilter.vue +85 -85
  45. package/src/ListRow.vue +204 -204
  46. package/src/LoadingMark.vue +175 -161
  47. package/src/Logo.vue +60 -60
  48. package/src/Modal.vue +78 -76
  49. package/src/ModalShell.vue +109 -107
  50. package/src/Pagination.vue +106 -106
  51. package/src/Popover.vue +180 -171
  52. package/src/PostCard.vue +210 -211
  53. package/src/ProgressBar.vue +90 -90
  54. package/src/RadioGroup.vue +177 -177
  55. package/src/RangeSlider.vue +183 -183
  56. package/src/RelativeDate.vue +35 -35
  57. package/src/ResizeHandle.vue +143 -143
  58. package/src/SearchInput.vue +192 -199
  59. package/src/Select.vue +644 -641
  60. package/src/Separator.vue +54 -54
  61. package/src/Skeleton.vue +82 -82
  62. package/src/Slider.vue +198 -198
  63. package/src/SortableList.vue +260 -260
  64. package/src/SplitPane.vue +68 -68
  65. package/src/StarButton.vue +40 -40
  66. package/src/Stepper.vue +141 -141
  67. package/src/SupportLinks.vue +93 -93
  68. package/src/TagInput.vue +297 -300
  69. package/src/Textarea.vue +57 -57
  70. package/src/Timeline.vue +92 -92
  71. package/src/ToastCard.vue +119 -119
  72. package/src/ToastHost.vue +40 -40
  73. package/src/Toggle.vue +36 -36
  74. package/src/TokenizedValue.vue +310 -310
  75. package/src/Toolbar.vue +110 -110
  76. package/src/VirtualList.vue +87 -87
  77. package/src/VisuallyHidden.vue +29 -29
  78. package/src/WpButton.vue +75 -75
  79. package/src/WpCheck.vue +104 -102
  80. package/src/WpIconButton.vue +107 -107
  81. package/src/WpImageZoom.vue +544 -544
  82. package/src/WpNumber.vue +178 -183
  83. package/src/WpSegmented.vue +175 -175
  84. package/src/WpSelect.vue +93 -89
  85. package/src/WpSwitch.vue +163 -163
  86. package/src/WpTabs.vue +188 -188
  87. package/src/_modal-motion.css +33 -33
  88. package/src/_skeleton.css +50 -50
  89. package/src/axis-color.ts +42 -42
  90. package/src/button.css +169 -169
  91. package/src/calendar.ts +59 -59
  92. package/src/clipboard.ts +50 -50
  93. package/src/colour-presets.ts +12 -12
  94. package/src/diff.ts +51 -51
  95. package/src/drop-zone.ts +41 -41
  96. package/src/field.css +50 -0
  97. package/src/flip.ts +237 -237
  98. package/src/floating-layer.ts +48 -0
  99. package/src/floating.ts +99 -99
  100. package/src/hsv.ts +100 -100
  101. package/src/icon-catalog.ts +52 -52
  102. package/src/image-zoom.ts +93 -93
  103. package/src/kind-colour.ts +28 -0
  104. package/src/logo-paths.ts +21 -21
  105. package/src/matrix-axis.ts +91 -91
  106. package/src/pagination.ts +27 -27
  107. package/src/platform-keys.ts +29 -29
  108. package/src/rich-tokenize.ts +357 -357
  109. package/src/select-types.ts +32 -32
  110. package/src/slider-math.ts +45 -45
  111. package/src/sortable.ts +22 -22
  112. package/src/theme/fonts/OFL-Fraunces.txt +93 -93
  113. package/src/theme/fonts/OFL-JetBrainsMono.txt +93 -93
  114. package/src/theme/fonts/OFL-Manrope.txt +93 -93
  115. package/src/theme/looks.css +428 -428
  116. package/src/theme/palettes.css +254 -254
  117. package/src/theme/tokens.css +2896 -2894
  118. package/src/tokens.ts +56 -56
  119. package/src/tooltip.css +43 -43
  120. package/src/tooltip.ts +146 -146
  121. package/src/useDialogFocus.ts +73 -73
  122. package/src/useGrowableField.ts +357 -357
  123. package/src/useModalKeyShield.ts +116 -116
  124. package/src/useToast.ts +48 -48
  125. package/src/wp-logo.svg +14 -14
  126. package/src/ChipToggle.vue +0 -92
  127. package/src/KindChip.vue +0 -53
  128. package/src/RatingBadge.vue +0 -42
package/src/HsvPicker.vue CHANGED
@@ -1,208 +1,208 @@
1
- <script setup lang="ts">
2
- /**
3
- * HsvPicker — saturation/value square + hue slider.
4
- *
5
- * Shared between manager ColorPicker / TweaksPanel AND the canvas
6
- * bundle modal. CSS uses `--wp-*` tokens with hardcoded fallbacks so
7
- * the picker renders inside the extension where the manager spacing
8
- * tokens (`--wp-space-*`) aren't loaded.
9
- *
10
- * Pure CSS gradient render — no canvas. The SV square stacks three
11
- * gradients to produce the HSV picker visual; the hue strip is a
12
- * single multi-stop linear gradient across the spectrum.
13
- *
14
- * Drag is driven by document-level `pointermove` + `pointerup`
15
- * listeners attached on pointerdown and detached on release. The
16
- * earlier `setPointerCapture`-based approach locked up the hue
17
- * slider when the SV picker reached an edge: in certain hosts
18
- * (notably the canvas Teleport popover), capture wasn't always
19
- * released cleanly, so subsequent pointerdown events on the hue
20
- * slider got rerouted back to the SV element and the slider read
21
- * as "stuck". Document-level handlers don't depend on element
22
- * capture and always cleanly tear down on pointerup, even when the
23
- * release happens outside the picker.
24
- */
25
- import { computed, onBeforeUnmount, ref, watch } from "vue";
26
- import { hexToHsv, hsvToHex, type Hsv } from "./hsv";
27
-
28
- interface Props {
29
- modelValue: string;
30
- ariaLabel?: string | undefined;
31
- }
32
- const props = defineProps<Props>();
33
-
34
- const emit = defineEmits<{
35
- (e: "update:modelValue", value: string): void;
36
- }>();
37
-
38
- const hsv = ref<Hsv>({ h: 0, s: 1, v: 1 });
39
-
40
- function syncFromProp(hex: string) {
41
- const parsed = hexToHsv(hex);
42
- if (!parsed) return;
43
- // Preserve the local hue when incoming RGB is pure black/white —
44
- // otherwise the user's hue selection snaps to 0 every time s or v
45
- // hits 0, which is jarring during a vertical drag.
46
- if (parsed.s === 0) parsed.h = hsv.value.h;
47
- hsv.value = parsed;
48
- }
49
-
50
- watch(() => props.modelValue, syncFromProp, { immediate: true });
51
-
52
- function emitHex() {
53
- emit("update:modelValue", hsvToHex(hsv.value));
54
- }
55
-
56
- const hueBg = computed(() => `hsl(${hsv.value.h}, 100%, 50%)`);
57
-
58
- const svEl = ref<HTMLDivElement | null>(null);
59
- const hueEl = ref<HTMLDivElement | null>(null);
60
-
61
- /** Document-level drag state. Only one drag can be active at a time
62
- * (one mouse / one finger), so a single `activeDrag` ref tracking
63
- * which surface owns the current pointer is sufficient. */
64
- let activeDrag: "sv" | "hue" | null = null;
65
-
66
- function handleSvMove(evt: PointerEvent) {
67
- const el = svEl.value;
68
- if (!el) return;
69
- const rect = el.getBoundingClientRect();
70
- const x = Math.max(0, Math.min(rect.width, evt.clientX - rect.left));
71
- const y = Math.max(0, Math.min(rect.height, evt.clientY - rect.top));
72
- hsv.value = { h: hsv.value.h, s: x / rect.width, v: 1 - (y / rect.height) };
73
- emitHex();
74
- }
75
-
76
- function handleHueMove(evt: PointerEvent) {
77
- const el = hueEl.value;
78
- if (!el) return;
79
- const rect = el.getBoundingClientRect();
80
- const x = Math.max(0, Math.min(rect.width, evt.clientX - rect.left));
81
- hsv.value = { h: (x / rect.width) * 360, s: hsv.value.s, v: hsv.value.v };
82
- emitHex();
83
- }
84
-
85
- function onDocPointerMove(evt: PointerEvent) {
86
- if (activeDrag === "sv") handleSvMove(evt);
87
- else if (activeDrag === "hue") handleHueMove(evt);
88
- }
89
-
90
- function onDocPointerUp() {
91
- activeDrag = null;
92
- document.removeEventListener("pointermove", onDocPointerMove);
93
- document.removeEventListener("pointerup", onDocPointerUp);
94
- document.removeEventListener("pointercancel", onDocPointerUp);
95
- }
96
-
97
- function startDrag(kind: "sv" | "hue", evt: PointerEvent) {
98
- activeDrag = kind;
99
- if (kind === "sv") handleSvMove(evt);
100
- else handleHueMove(evt);
101
- document.addEventListener("pointermove", onDocPointerMove);
102
- document.addEventListener("pointerup", onDocPointerUp);
103
- document.addEventListener("pointercancel", onDocPointerUp);
104
- }
105
-
106
- function onSvPointerDown(evt: PointerEvent) {
107
- evt.preventDefault();
108
- startDrag("sv", evt);
109
- }
110
- function onHuePointerDown(evt: PointerEvent) {
111
- evt.preventDefault();
112
- startDrag("hue", evt);
113
- }
114
-
115
- onBeforeUnmount(onDocPointerUp);
116
-
117
- const svCursorStyle = computed(() => ({
118
- left: `${hsv.value.s * 100}%`,
119
- top: `${(1 - hsv.value.v) * 100}%`,
120
- }));
121
- const hueCursorStyle = computed(() => ({
122
- left: `${(hsv.value.h / 360) * 100}%`,
123
- }));
124
- </script>
125
-
126
- <template>
127
- <div class="wp-hsv-picker" :aria-label="ariaLabel">
128
- <div
129
- ref="svEl"
130
- class="wp-hsv-picker__sv"
131
- :style="{ '--wp-hsv-hue': hueBg }"
132
- :aria-label="`Saturation and brightness, current ${Math.round(hsv.s * 100)}% / ${Math.round(hsv.v * 100)}%`"
133
- data-test="hsv-sv"
134
- @pointerdown="onSvPointerDown"
135
- >
136
- <div class="wp-hsv-picker__sv-cursor" :style="svCursorStyle" />
137
- </div>
138
- <div
139
- ref="hueEl"
140
- class="wp-hsv-picker__hue"
141
- :aria-label="`Hue, current ${Math.round(hsv.h)}°`"
142
- data-test="hsv-hue"
143
- @pointerdown="onHuePointerDown"
144
- >
145
- <div class="wp-hsv-picker__hue-cursor" :style="hueCursorStyle" />
146
- </div>
147
- </div>
148
- </template>
149
-
150
- <style scoped>
151
- .wp-hsv-picker { display: flex; flex-direction: column; gap: var(--wp-space-4, 8px); width: 100%; }
152
- .wp-hsv-picker__sv {
153
- position: relative;
154
- width: 100%;
155
- height: 120px;
156
- border-radius: var(--wp-radius-sm, 4px);
157
- border: 1px solid var(--wp-border, #3a3a3a);
158
- cursor: crosshair;
159
- touch-action: none;
160
- user-select: none;
161
- background:
162
- linear-gradient(to top, #000, transparent),
163
- linear-gradient(to right, #fff, transparent),
164
- var(--wp-hsv-hue, hsl(0, 100%, 50%));
165
- }
166
- .wp-hsv-picker__sv-cursor {
167
- position: absolute;
168
- width: 14px;
169
- height: 14px;
170
- border-radius: 50%; /* round: picker cursor on the colour field */
171
- border: 2px solid #fff;
172
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 1px 2px rgba(0, 0, 0, 0.45);
173
- transform: translate(-50%, -50%);
174
- pointer-events: none;
175
- }
176
- .wp-hsv-picker__hue {
177
- position: relative;
178
- width: 100%;
179
- height: 12px;
180
- border-radius: var(--wp-radius-sm, 4px);
181
- border: 1px solid var(--wp-border, #3a3a3a);
182
- cursor: ew-resize;
183
- touch-action: none;
184
- user-select: none;
185
- background: linear-gradient(
186
- to right,
187
- hsl(0, 100%, 50%),
188
- hsl(60, 100%, 50%),
189
- hsl(120, 100%, 50%),
190
- hsl(180, 100%, 50%),
191
- hsl(240, 100%, 50%),
192
- hsl(300, 100%, 50%),
193
- hsl(360, 100%, 50%)
194
- );
195
- }
196
- .wp-hsv-picker__hue-cursor {
197
- position: absolute;
198
- top: 50%;
199
- width: 12px;
200
- height: 16px;
201
- border-radius: var(--wp-radius-sm, 4px);
202
- border: 2px solid #fff;
203
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 1px 2px rgba(0, 0, 0, 0.45);
204
- transform: translate(-50%, -50%);
205
- pointer-events: none;
206
- background: transparent;
207
- }
208
- </style>
1
+ <script setup lang="ts">
2
+ /**
3
+ * HsvPicker — saturation/value square + hue slider.
4
+ *
5
+ * Shared between manager ColorPicker / TweaksPanel AND the canvas
6
+ * bundle modal. CSS uses `--wp-*` tokens with hardcoded fallbacks so
7
+ * the picker renders inside the extension where the manager spacing
8
+ * tokens (`--wp-space-*`) aren't loaded.
9
+ *
10
+ * Pure CSS gradient render — no canvas. The SV square stacks three
11
+ * gradients to produce the HSV picker visual; the hue strip is a
12
+ * single multi-stop linear gradient across the spectrum.
13
+ *
14
+ * Drag is driven by document-level `pointermove` + `pointerup`
15
+ * listeners attached on pointerdown and detached on release. The
16
+ * earlier `setPointerCapture`-based approach locked up the hue
17
+ * slider when the SV picker reached an edge: in certain hosts
18
+ * (notably the canvas Teleport popover), capture wasn't always
19
+ * released cleanly, so subsequent pointerdown events on the hue
20
+ * slider got rerouted back to the SV element and the slider read
21
+ * as "stuck". Document-level handlers don't depend on element
22
+ * capture and always cleanly tear down on pointerup, even when the
23
+ * release happens outside the picker.
24
+ */
25
+ import { computed, onBeforeUnmount, ref, watch } from "vue";
26
+ import { hexToHsv, hsvToHex, type Hsv } from "./hsv";
27
+
28
+ interface Props {
29
+ modelValue: string;
30
+ ariaLabel?: string | undefined;
31
+ }
32
+ const props = defineProps<Props>();
33
+
34
+ const emit = defineEmits<{
35
+ (e: "update:modelValue", value: string): void;
36
+ }>();
37
+
38
+ const hsv = ref<Hsv>({ h: 0, s: 1, v: 1 });
39
+
40
+ function syncFromProp(hex: string) {
41
+ const parsed = hexToHsv(hex);
42
+ if (!parsed) return;
43
+ // Preserve the local hue when incoming RGB is pure black/white —
44
+ // otherwise the user's hue selection snaps to 0 every time s or v
45
+ // hits 0, which is jarring during a vertical drag.
46
+ if (parsed.s === 0) parsed.h = hsv.value.h;
47
+ hsv.value = parsed;
48
+ }
49
+
50
+ watch(() => props.modelValue, syncFromProp, { immediate: true });
51
+
52
+ function emitHex() {
53
+ emit("update:modelValue", hsvToHex(hsv.value));
54
+ }
55
+
56
+ const hueBg = computed(() => `hsl(${hsv.value.h}, 100%, 50%)`);
57
+
58
+ const svEl = ref<HTMLDivElement | null>(null);
59
+ const hueEl = ref<HTMLDivElement | null>(null);
60
+
61
+ /** Document-level drag state. Only one drag can be active at a time
62
+ * (one mouse / one finger), so a single `activeDrag` ref tracking
63
+ * which surface owns the current pointer is sufficient. */
64
+ let activeDrag: "sv" | "hue" | null = null;
65
+
66
+ function handleSvMove(evt: PointerEvent) {
67
+ const el = svEl.value;
68
+ if (!el) return;
69
+ const rect = el.getBoundingClientRect();
70
+ const x = Math.max(0, Math.min(rect.width, evt.clientX - rect.left));
71
+ const y = Math.max(0, Math.min(rect.height, evt.clientY - rect.top));
72
+ hsv.value = { h: hsv.value.h, s: x / rect.width, v: 1 - (y / rect.height) };
73
+ emitHex();
74
+ }
75
+
76
+ function handleHueMove(evt: PointerEvent) {
77
+ const el = hueEl.value;
78
+ if (!el) return;
79
+ const rect = el.getBoundingClientRect();
80
+ const x = Math.max(0, Math.min(rect.width, evt.clientX - rect.left));
81
+ hsv.value = { h: (x / rect.width) * 360, s: hsv.value.s, v: hsv.value.v };
82
+ emitHex();
83
+ }
84
+
85
+ function onDocPointerMove(evt: PointerEvent) {
86
+ if (activeDrag === "sv") handleSvMove(evt);
87
+ else if (activeDrag === "hue") handleHueMove(evt);
88
+ }
89
+
90
+ function onDocPointerUp() {
91
+ activeDrag = null;
92
+ document.removeEventListener("pointermove", onDocPointerMove);
93
+ document.removeEventListener("pointerup", onDocPointerUp);
94
+ document.removeEventListener("pointercancel", onDocPointerUp);
95
+ }
96
+
97
+ function startDrag(kind: "sv" | "hue", evt: PointerEvent) {
98
+ activeDrag = kind;
99
+ if (kind === "sv") handleSvMove(evt);
100
+ else handleHueMove(evt);
101
+ document.addEventListener("pointermove", onDocPointerMove);
102
+ document.addEventListener("pointerup", onDocPointerUp);
103
+ document.addEventListener("pointercancel", onDocPointerUp);
104
+ }
105
+
106
+ function onSvPointerDown(evt: PointerEvent) {
107
+ evt.preventDefault();
108
+ startDrag("sv", evt);
109
+ }
110
+ function onHuePointerDown(evt: PointerEvent) {
111
+ evt.preventDefault();
112
+ startDrag("hue", evt);
113
+ }
114
+
115
+ onBeforeUnmount(onDocPointerUp);
116
+
117
+ const svCursorStyle = computed(() => ({
118
+ left: `${hsv.value.s * 100}%`,
119
+ top: `${(1 - hsv.value.v) * 100}%`,
120
+ }));
121
+ const hueCursorStyle = computed(() => ({
122
+ left: `${(hsv.value.h / 360) * 100}%`,
123
+ }));
124
+ </script>
125
+
126
+ <template>
127
+ <div class="wp-hsv-picker" :aria-label="ariaLabel">
128
+ <div
129
+ ref="svEl"
130
+ class="wp-hsv-picker__sv"
131
+ :style="{ '--wp-hsv-hue': hueBg }"
132
+ :aria-label="`Saturation and brightness, current ${Math.round(hsv.s * 100)}% / ${Math.round(hsv.v * 100)}%`"
133
+ data-test="hsv-sv"
134
+ @pointerdown="onSvPointerDown"
135
+ >
136
+ <div class="wp-hsv-picker__sv-cursor" :style="svCursorStyle" />
137
+ </div>
138
+ <div
139
+ ref="hueEl"
140
+ class="wp-hsv-picker__hue"
141
+ :aria-label="`Hue, current ${Math.round(hsv.h)}°`"
142
+ data-test="hsv-hue"
143
+ @pointerdown="onHuePointerDown"
144
+ >
145
+ <div class="wp-hsv-picker__hue-cursor" :style="hueCursorStyle" />
146
+ </div>
147
+ </div>
148
+ </template>
149
+
150
+ <style scoped>
151
+ .wp-hsv-picker { display: flex; flex-direction: column; gap: var(--wp-space-4, 8px); width: 100%; }
152
+ .wp-hsv-picker__sv {
153
+ position: relative;
154
+ width: 100%;
155
+ height: 120px;
156
+ border-radius: var(--wp-radius-sm, 4px);
157
+ border: 1px solid var(--wp-border, #3a3a3a);
158
+ cursor: crosshair;
159
+ touch-action: none;
160
+ user-select: none;
161
+ background:
162
+ linear-gradient(to top, #000, transparent),
163
+ linear-gradient(to right, #fff, transparent),
164
+ var(--wp-hsv-hue, hsl(0, 100%, 50%));
165
+ }
166
+ .wp-hsv-picker__sv-cursor {
167
+ position: absolute;
168
+ width: 14px;
169
+ height: 14px;
170
+ border-radius: 50%; /* round: picker cursor on the colour field */
171
+ border: 2px solid #fff;
172
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 1px 2px rgba(0, 0, 0, 0.45);
173
+ transform: translate(-50%, -50%);
174
+ pointer-events: none;
175
+ }
176
+ .wp-hsv-picker__hue {
177
+ position: relative;
178
+ width: 100%;
179
+ height: 12px;
180
+ border-radius: var(--wp-radius-sm, 4px);
181
+ border: 1px solid var(--wp-border, #3a3a3a);
182
+ cursor: ew-resize;
183
+ touch-action: none;
184
+ user-select: none;
185
+ background: linear-gradient(
186
+ to right,
187
+ hsl(0, 100%, 50%),
188
+ hsl(60, 100%, 50%),
189
+ hsl(120, 100%, 50%),
190
+ hsl(180, 100%, 50%),
191
+ hsl(240, 100%, 50%),
192
+ hsl(300, 100%, 50%),
193
+ hsl(360, 100%, 50%)
194
+ );
195
+ }
196
+ .wp-hsv-picker__hue-cursor {
197
+ position: absolute;
198
+ top: 50%;
199
+ width: 12px;
200
+ height: 16px;
201
+ border-radius: var(--wp-radius-sm, 4px);
202
+ border: 2px solid #fff;
203
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 1px 2px rgba(0, 0, 0, 0.45);
204
+ transform: translate(-50%, -50%);
205
+ pointer-events: none;
206
+ background: transparent;
207
+ }
208
+ </style>
package/src/Icon.vue CHANGED
@@ -1,39 +1,39 @@
1
- <script lang="ts">
2
- /**
3
- * Canonical icon sizes. Use these instead of raw numbers on `:size`.
4
- *
5
- * ICON_SM (12) — micro indicators, badge glyphs, tight pill icons
6
- * ICON_MD (14) — default toolbar / sidebar / inline icons
7
- * ICON_LG (18) — emphasized icons (CTA buttons, empty-state subheadings,
8
- * panel-header glyphs)
9
- *
10
- * Outliers (e.g. very large empty-state icons at 48-80px) stay as raw
11
- * numbers — flag the locations in PR review so we can decide whether
12
- * to grow the scale.
13
- */
14
- export const ICON_SM = 12;
15
- export const ICON_MD = 14;
16
- export const ICON_LG = 18;
17
- </script>
18
-
19
- <script setup lang="ts">
20
- import { computed } from "vue";
21
-
22
- interface Props {
23
- name: string;
24
- size?: number | undefined;
25
- }
26
- const props = defineProps<Props>();
27
-
28
- const className = computed(() => {
29
- // Accept either bare name ("plus", "check-circle") or already-prefixed ("pi-plus").
30
- const n = props.name.startsWith("pi-") ? props.name : `pi-${props.name}`;
31
- return `pi ${n}`;
32
- });
33
-
34
- const style = computed(() => (props.size ? { fontSize: `${props.size}px` } : undefined));
35
- </script>
36
-
37
- <template>
38
- <i :class="className" :style="style" aria-hidden="true" />
39
- </template>
1
+ <script lang="ts">
2
+ /**
3
+ * Canonical icon sizes. Use these instead of raw numbers on `:size`.
4
+ *
5
+ * ICON_SM (12) — micro indicators, badge glyphs, tight pill icons
6
+ * ICON_MD (14) — default toolbar / sidebar / inline icons
7
+ * ICON_LG (18) — emphasized icons (CTA buttons, empty-state subheadings,
8
+ * panel-header glyphs)
9
+ *
10
+ * Outliers (e.g. very large empty-state icons at 48-80px) stay as raw
11
+ * numbers — flag the locations in PR review so we can decide whether
12
+ * to grow the scale.
13
+ */
14
+ export const ICON_SM = 12;
15
+ export const ICON_MD = 14;
16
+ export const ICON_LG = 18;
17
+ </script>
18
+
19
+ <script setup lang="ts">
20
+ import { computed } from "vue";
21
+
22
+ interface Props {
23
+ name: string;
24
+ size?: number | undefined;
25
+ }
26
+ const props = defineProps<Props>();
27
+
28
+ const className = computed(() => {
29
+ // Accept either bare name ("plus", "check-circle") or already-prefixed ("pi-plus").
30
+ const n = props.name.startsWith("pi-") ? props.name : `pi-${props.name}`;
31
+ return `pi ${n}`;
32
+ });
33
+
34
+ const style = computed(() => (props.size ? { fontSize: `${props.size}px` } : undefined));
35
+ </script>
36
+
37
+ <template>
38
+ <i :class="className" :style="style" aria-hidden="true" />
39
+ </template>