orio-ui 1.19.0 → 1.23.2

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 (161) hide show
  1. package/README.md +12 -5
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +5 -2
  4. package/dist/runtime/canvas.d.ts +21 -0
  5. package/dist/runtime/canvas.js +49 -0
  6. package/dist/runtime/components/Button.vue +2 -1
  7. package/dist/runtime/components/Canvas/REQUIREMENTS.md +174 -0
  8. package/dist/runtime/components/Canvas/components/Stage.d.vue.ts +3 -0
  9. package/dist/runtime/components/Canvas/components/Stage.vue +150 -0
  10. package/dist/runtime/components/Canvas/components/Stage.vue.d.ts +3 -0
  11. package/dist/runtime/components/Canvas/components/ToolButton.d.vue.ts +24 -0
  12. package/dist/runtime/components/Canvas/components/ToolButton.vue +62 -0
  13. package/dist/runtime/components/Canvas/components/ToolButton.vue.d.ts +24 -0
  14. package/dist/runtime/components/Canvas/components/Toolbar.d.vue.ts +24 -0
  15. package/dist/runtime/components/Canvas/components/Toolbar.vue +48 -0
  16. package/dist/runtime/components/Canvas/components/Toolbar.vue.d.ts +24 -0
  17. package/dist/runtime/components/Canvas/composables/useCanvasHistory.d.ts +17 -0
  18. package/dist/runtime/components/Canvas/composables/useCanvasHistory.js +76 -0
  19. package/dist/runtime/components/Canvas/composables/useCanvasNodes.d.ts +13 -0
  20. package/dist/runtime/components/Canvas/composables/useCanvasNodes.js +60 -0
  21. package/dist/runtime/components/Canvas/composables/useCanvasSetup.d.ts +5 -0
  22. package/dist/runtime/components/Canvas/composables/useCanvasSetup.js +19 -0
  23. package/dist/runtime/components/Canvas/context.d.ts +38 -0
  24. package/dist/runtime/components/Canvas/context.js +11 -0
  25. package/dist/runtime/components/Canvas/index.d.vue.ts +77 -0
  26. package/dist/runtime/components/Canvas/index.vue +208 -0
  27. package/dist/runtime/components/Canvas/index.vue.d.ts +77 -0
  28. package/dist/runtime/components/Canvas/registry.d.ts +1 -0
  29. package/dist/runtime/components/Canvas/registry.js +2 -0
  30. package/dist/runtime/components/Canvas/tools/ColorPickerWidget.d.vue.ts +7 -0
  31. package/dist/runtime/components/Canvas/tools/ColorPickerWidget.vue +32 -0
  32. package/dist/runtime/components/Canvas/tools/ColorPickerWidget.vue.d.ts +7 -0
  33. package/dist/runtime/components/Canvas/tools/clearTool.d.ts +1 -0
  34. package/dist/runtime/components/Canvas/tools/clearTool.js +16 -0
  35. package/dist/runtime/components/Canvas/tools/colorPickerTool.d.ts +6 -0
  36. package/dist/runtime/components/Canvas/tools/colorPickerTool.js +15 -0
  37. package/dist/runtime/components/Canvas/tools/drawTool.d.ts +16 -0
  38. package/dist/runtime/components/Canvas/tools/drawTool.js +92 -0
  39. package/dist/runtime/components/Canvas/tools/eraseTool.d.ts +5 -0
  40. package/dist/runtime/components/Canvas/tools/eraseTool.js +62 -0
  41. package/dist/runtime/components/Canvas/tools/exportTool.d.ts +18 -0
  42. package/dist/runtime/components/Canvas/tools/exportTool.js +89 -0
  43. package/dist/runtime/components/Canvas/tools/highlightTool.d.ts +11 -0
  44. package/dist/runtime/components/Canvas/tools/highlightTool.js +51 -0
  45. package/dist/runtime/components/Canvas/tools/hitTest.d.ts +20 -0
  46. package/dist/runtime/components/Canvas/tools/hitTest.js +111 -0
  47. package/dist/runtime/components/Canvas/tools/imageTool.d.ts +18 -0
  48. package/dist/runtime/components/Canvas/tools/imageTool.js +163 -0
  49. package/dist/runtime/components/Canvas/tools/moveTool.d.ts +5 -0
  50. package/dist/runtime/components/Canvas/tools/moveTool.js +94 -0
  51. package/dist/runtime/components/Canvas/tools/redoTool.d.ts +1 -0
  52. package/dist/runtime/components/Canvas/tools/redoTool.js +17 -0
  53. package/dist/runtime/components/Canvas/tools/resizeTool.d.ts +7 -0
  54. package/dist/runtime/components/Canvas/tools/resizeTool.js +132 -0
  55. package/dist/runtime/components/Canvas/tools/rotateTool.d.ts +5 -0
  56. package/dist/runtime/components/Canvas/tools/rotateTool.js +109 -0
  57. package/dist/runtime/components/Canvas/tools/textTool.d.ts +14 -0
  58. package/dist/runtime/components/Canvas/tools/textTool.js +99 -0
  59. package/dist/runtime/components/Canvas/tools/tooltips/Clear.d.vue.ts +3 -0
  60. package/dist/runtime/components/Canvas/tools/tooltips/Clear.vue +12 -0
  61. package/dist/runtime/components/Canvas/tools/tooltips/Clear.vue.d.ts +3 -0
  62. package/dist/runtime/components/Canvas/tools/tooltips/Draw.d.vue.ts +3 -0
  63. package/dist/runtime/components/Canvas/tools/tooltips/Draw.vue +12 -0
  64. package/dist/runtime/components/Canvas/tools/tooltips/Draw.vue.d.ts +3 -0
  65. package/dist/runtime/components/Canvas/tools/tooltips/Erase.d.vue.ts +3 -0
  66. package/dist/runtime/components/Canvas/tools/tooltips/Erase.vue +12 -0
  67. package/dist/runtime/components/Canvas/tools/tooltips/Erase.vue.d.ts +3 -0
  68. package/dist/runtime/components/Canvas/tools/tooltips/Export.d.vue.ts +3 -0
  69. package/dist/runtime/components/Canvas/tools/tooltips/Export.vue +13 -0
  70. package/dist/runtime/components/Canvas/tools/tooltips/Export.vue.d.ts +3 -0
  71. package/dist/runtime/components/Canvas/tools/tooltips/Highlight.d.vue.ts +3 -0
  72. package/dist/runtime/components/Canvas/tools/tooltips/Highlight.vue +12 -0
  73. package/dist/runtime/components/Canvas/tools/tooltips/Highlight.vue.d.ts +3 -0
  74. package/dist/runtime/components/Canvas/tools/tooltips/Image.d.vue.ts +3 -0
  75. package/dist/runtime/components/Canvas/tools/tooltips/Image.vue +13 -0
  76. package/dist/runtime/components/Canvas/tools/tooltips/Image.vue.d.ts +3 -0
  77. package/dist/runtime/components/Canvas/tools/tooltips/Move.d.vue.ts +3 -0
  78. package/dist/runtime/components/Canvas/tools/tooltips/Move.vue +13 -0
  79. package/dist/runtime/components/Canvas/tools/tooltips/Move.vue.d.ts +3 -0
  80. package/dist/runtime/components/Canvas/tools/tooltips/Redo.d.vue.ts +3 -0
  81. package/dist/runtime/components/Canvas/tools/tooltips/Redo.vue +13 -0
  82. package/dist/runtime/components/Canvas/tools/tooltips/Redo.vue.d.ts +3 -0
  83. package/dist/runtime/components/Canvas/tools/tooltips/Resize.d.vue.ts +3 -0
  84. package/dist/runtime/components/Canvas/tools/tooltips/Resize.vue +13 -0
  85. package/dist/runtime/components/Canvas/tools/tooltips/Resize.vue.d.ts +3 -0
  86. package/dist/runtime/components/Canvas/tools/tooltips/Rotate.d.vue.ts +3 -0
  87. package/dist/runtime/components/Canvas/tools/tooltips/Rotate.vue +13 -0
  88. package/dist/runtime/components/Canvas/tools/tooltips/Rotate.vue.d.ts +3 -0
  89. package/dist/runtime/components/Canvas/tools/tooltips/Text.d.vue.ts +3 -0
  90. package/dist/runtime/components/Canvas/tools/tooltips/Text.vue +13 -0
  91. package/dist/runtime/components/Canvas/tools/tooltips/Text.vue.d.ts +3 -0
  92. package/dist/runtime/components/Canvas/tools/tooltips/Transform.d.vue.ts +3 -0
  93. package/dist/runtime/components/Canvas/tools/tooltips/Transform.vue +14 -0
  94. package/dist/runtime/components/Canvas/tools/tooltips/Transform.vue.d.ts +3 -0
  95. package/dist/runtime/components/Canvas/tools/tooltips/Undo.d.vue.ts +3 -0
  96. package/dist/runtime/components/Canvas/tools/tooltips/Undo.vue +13 -0
  97. package/dist/runtime/components/Canvas/tools/tooltips/Undo.vue.d.ts +3 -0
  98. package/dist/runtime/components/Canvas/tools/transformHandles.d.ts +74 -0
  99. package/dist/runtime/components/Canvas/tools/transformHandles.js +191 -0
  100. package/dist/runtime/components/Canvas/tools/transformTool.d.ts +7 -0
  101. package/dist/runtime/components/Canvas/tools/transformTool.js +210 -0
  102. package/dist/runtime/components/Canvas/tools/undoTool.d.ts +1 -0
  103. package/dist/runtime/components/Canvas/tools/undoTool.js +17 -0
  104. package/dist/runtime/components/Canvas/types.d.ts +125 -0
  105. package/dist/runtime/components/Canvas/types.js +3 -0
  106. package/dist/runtime/components/CheckBox.vue +6 -3
  107. package/dist/runtime/components/CheckboxGroup.vue +2 -1
  108. package/dist/runtime/components/ControlElement.d.vue.ts +5 -0
  109. package/dist/runtime/components/ControlElement.vue +19 -3
  110. package/dist/runtime/components/ControlElement.vue.d.ts +5 -0
  111. package/dist/runtime/components/DateRangePicker.vue +16 -4
  112. package/dist/runtime/components/Icon.vue +2 -2
  113. package/dist/runtime/components/Input.vue +2 -1
  114. package/dist/runtime/components/ListItem.d.vue.ts +29 -0
  115. package/dist/runtime/components/ListItem.vue +72 -0
  116. package/dist/runtime/components/ListItem.vue.d.ts +29 -0
  117. package/dist/runtime/components/LocaleSwitcher.d.vue.ts +13 -0
  118. package/dist/runtime/components/LocaleSwitcher.vue +43 -0
  119. package/dist/runtime/components/LocaleSwitcher.vue.d.ts +13 -0
  120. package/dist/runtime/components/NavButton.vue +2 -1
  121. package/dist/runtime/components/NumberInput/Horizontal.vue +2 -1
  122. package/dist/runtime/components/NumberInput/Vertical.vue +2 -1
  123. package/dist/runtime/components/NumberInput/index.vue +2 -1
  124. package/dist/runtime/components/RadioButton.vue +2 -1
  125. package/dist/runtime/components/Selector.vue +24 -22
  126. package/dist/runtime/components/SwitchButton.vue +2 -1
  127. package/dist/runtime/components/Tag.d.vue.ts +3 -2
  128. package/dist/runtime/components/Tag.vue +1 -0
  129. package/dist/runtime/components/Tag.vue.d.ts +3 -2
  130. package/dist/runtime/components/TaggableSelector.d.vue.ts +16 -0
  131. package/dist/runtime/components/TaggableSelector.vue +35 -0
  132. package/dist/runtime/components/TaggableSelector.vue.d.ts +16 -0
  133. package/dist/runtime/components/Textarea.vue +2 -1
  134. package/dist/runtime/components/Tooltip.vue +17 -7
  135. package/dist/runtime/components/ZoomableContainer.d.vue.ts +48 -0
  136. package/dist/runtime/components/ZoomableContainer.vue +238 -0
  137. package/dist/runtime/components/ZoomableContainer.vue.d.ts +48 -0
  138. package/dist/runtime/components/gallery/Carousel.vue +1 -1
  139. package/dist/runtime/components/gallery/CarouselPreview.d.vue.ts +31 -0
  140. package/dist/runtime/components/gallery/CarouselPreview.vue +64 -0
  141. package/dist/runtime/components/gallery/CarouselPreview.vue.d.ts +31 -0
  142. package/dist/runtime/components/view/Dates.vue +5 -3
  143. package/dist/runtime/components/view/KeyBinds.d.vue.ts +7 -0
  144. package/dist/runtime/components/view/KeyBinds.vue +36 -0
  145. package/dist/runtime/components/view/KeyBinds.vue.d.ts +7 -0
  146. package/dist/runtime/components/view/Text.vue +4 -4
  147. package/dist/runtime/composables/useInertia.d.ts +10 -0
  148. package/dist/runtime/composables/useInertia.js +49 -0
  149. package/dist/runtime/composables/usePinchZoom.d.ts +13 -0
  150. package/dist/runtime/composables/usePinchZoom.js +66 -0
  151. package/dist/runtime/composables/useValidation.js +11 -1
  152. package/dist/runtime/i18n/en.json +20 -0
  153. package/dist/runtime/i18n/index.d.ts +11 -0
  154. package/dist/runtime/i18n/index.js +19 -0
  155. package/dist/runtime/i18n/uk.json +20 -0
  156. package/dist/runtime/index.d.ts +8 -1
  157. package/dist/runtime/index.js +19 -1
  158. package/dist/runtime/plugins/i18n.d.ts +2 -0
  159. package/dist/runtime/plugins/i18n.js +18 -0
  160. package/dist/runtime/utils/icon-registry.js +13 -1
  161. package/package.json +9 -4
@@ -0,0 +1,238 @@
1
+ <script setup>
2
+ import { computed, ref, onMounted, onUnmounted, useTemplateRef } from "vue";
3
+ import { useResizeObserver, useEventListener } from "@vueuse/core";
4
+ import { usePinchZoom } from "../composables/usePinchZoom";
5
+ import { useInertia } from "../composables/useInertia";
6
+ const props = defineProps({
7
+ minScale: { type: Number, required: false, default: 0.1 },
8
+ maxScale: { type: Number, required: false, default: 10 },
9
+ initialScale: { type: Number, required: false, default: 1 },
10
+ zoomSpeed: { type: Number, required: false, default: 15e-4 },
11
+ wheelPanSpeed: { type: Number, required: false, default: 1 }
12
+ });
13
+ const emit = defineEmits(["update:scale", "update:translate"]);
14
+ const viewportEl = useTemplateRef("viewportEl");
15
+ const worldEl = useTemplateRef("worldEl");
16
+ const scale = ref(props.initialScale);
17
+ const tx = ref(0);
18
+ const ty = ref(0);
19
+ const viewport = ref({ w: 0, h: 0 });
20
+ const world = ref({ w: 0, h: 0 });
21
+ const spaceHeld = ref(false);
22
+ let centered = false;
23
+ function clamp(v, a, b) {
24
+ const lo = Math.min(a, b);
25
+ const hi = Math.max(a, b);
26
+ return Math.max(lo, Math.min(hi, v));
27
+ }
28
+ function applyBounds() {
29
+ const vw = viewport.value.w;
30
+ const vh = viewport.value.h;
31
+ const ww = world.value.w * scale.value;
32
+ const wh = world.value.h * scale.value;
33
+ tx.value = clamp(tx.value, vw / 2 - ww, vw / 2);
34
+ ty.value = clamp(ty.value, vh / 2 - wh, vh / 2);
35
+ }
36
+ function emitState() {
37
+ emit("update:scale", scale.value);
38
+ emit("update:translate", tx.value, ty.value);
39
+ }
40
+ function setScaleAt(target, px, py) {
41
+ const next = clamp(target, props.minScale, props.maxScale);
42
+ const k = next / scale.value;
43
+ tx.value = px - (px - tx.value) * k;
44
+ ty.value = py - (py - ty.value) * k;
45
+ scale.value = next;
46
+ applyBounds();
47
+ emitState();
48
+ }
49
+ function panBy(dx, dy) {
50
+ tx.value += dx;
51
+ ty.value += dy;
52
+ applyBounds();
53
+ emitState();
54
+ }
55
+ function centerWorld() {
56
+ const { w: vw, h: vh } = viewport.value;
57
+ const { w: ww, h: wh } = world.value;
58
+ tx.value = (vw - ww * scale.value) / 2;
59
+ ty.value = (vh - wh * scale.value) / 2;
60
+ applyBounds();
61
+ emitState();
62
+ }
63
+ function resetView() {
64
+ scale.value = props.initialScale;
65
+ centerWorld();
66
+ }
67
+ const inertia = useInertia(panBy);
68
+ let pinchBaseScale = 1;
69
+ const pinch = usePinchZoom({
70
+ onPinchStart() {
71
+ dragId = null;
72
+ pinchBaseScale = scale.value;
73
+ },
74
+ onPinchMove(scaleFactor, midX, midY, dx, dy) {
75
+ const rect = viewportEl.value.getBoundingClientRect();
76
+ setScaleAt(pinchBaseScale * scaleFactor, midX - rect.left, midY - rect.top);
77
+ if (dx !== 0 || dy !== 0) panBy(dx, dy);
78
+ },
79
+ onSingleDown(e) {
80
+ e.preventDefault();
81
+ dragId = e.pointerId;
82
+ lastX = e.clientX;
83
+ lastY = e.clientY;
84
+ inertia.resetTime();
85
+ },
86
+ onSingleUp(id, x, y) {
87
+ dragId = id;
88
+ lastX = x;
89
+ lastY = y;
90
+ inertia.resetTime();
91
+ inertia.stop();
92
+ }
93
+ });
94
+ function onWheel(e) {
95
+ e.preventDefault();
96
+ if (e.ctrlKey || e.metaKey) {
97
+ const rect = viewportEl.value.getBoundingClientRect();
98
+ const px = e.clientX - rect.left;
99
+ const py = e.clientY - rect.top;
100
+ const factor = Math.exp(-e.deltaY * props.zoomSpeed);
101
+ setScaleAt(scale.value * factor, px, py);
102
+ return;
103
+ }
104
+ let dx = -e.deltaX * props.wheelPanSpeed;
105
+ let dy = -e.deltaY * props.wheelPanSpeed;
106
+ if (e.shiftKey && dx === 0) {
107
+ dx = dy;
108
+ dy = 0;
109
+ }
110
+ panBy(dx, dy);
111
+ }
112
+ let dragId = null;
113
+ let lastX = 0;
114
+ let lastY = 0;
115
+ function shouldPan(e) {
116
+ if (e.button === 1) return true;
117
+ if (spaceHeld.value) return true;
118
+ if (e.target === viewportEl.value) return true;
119
+ return false;
120
+ }
121
+ function onPointerDown(e) {
122
+ inertia.stop();
123
+ if (e.pointerType === "touch") {
124
+ pinch.onPointerDown(e);
125
+ return;
126
+ }
127
+ if (!shouldPan(e)) return;
128
+ e.preventDefault();
129
+ dragId = e.pointerId;
130
+ lastX = e.clientX;
131
+ lastY = e.clientY;
132
+ inertia.resetTime();
133
+ e.currentTarget.setPointerCapture(e.pointerId);
134
+ }
135
+ function onPointerMove(e) {
136
+ if (e.pointerType === "touch") {
137
+ if (pinch.onPointerMove(e)) return;
138
+ }
139
+ if (dragId !== e.pointerId) return;
140
+ const dx = e.clientX - lastX;
141
+ const dy = e.clientY - lastY;
142
+ lastX = e.clientX;
143
+ lastY = e.clientY;
144
+ inertia.trackMove(dx, dy);
145
+ panBy(dx, dy);
146
+ }
147
+ function onPointerUp(e) {
148
+ if (e.pointerType === "touch") {
149
+ if (pinch.onPointerUp(e)) return;
150
+ }
151
+ if (dragId !== e.pointerId) return;
152
+ dragId = null;
153
+ inertia.release();
154
+ try {
155
+ e.currentTarget.releasePointerCapture(e.pointerId);
156
+ } catch {
157
+ }
158
+ }
159
+ useEventListener("keydown", (e) => {
160
+ if (e.code === "Space") spaceHeld.value = true;
161
+ });
162
+ useEventListener("keyup", (e) => {
163
+ if (e.code === "Space") spaceHeld.value = false;
164
+ });
165
+ useResizeObserver(viewportEl, (entries) => {
166
+ const r = entries[0].contentRect;
167
+ viewport.value = { w: r.width, h: r.height };
168
+ if (!centered && world.value.w && world.value.h) {
169
+ centered = true;
170
+ centerWorld();
171
+ } else {
172
+ applyBounds();
173
+ }
174
+ });
175
+ useResizeObserver(worldEl, (entries) => {
176
+ const r = entries[0].contentRect;
177
+ world.value = { w: r.width, h: r.height };
178
+ if (!centered && viewport.value.w && viewport.value.h) {
179
+ centered = true;
180
+ centerWorld();
181
+ } else {
182
+ applyBounds();
183
+ }
184
+ });
185
+ onMounted(() => {
186
+ const vEl = viewportEl.value;
187
+ const wEl = worldEl.value;
188
+ if (!vEl || !wEl) return;
189
+ viewport.value = { w: vEl.clientWidth, h: vEl.clientHeight };
190
+ world.value = { w: wEl.offsetWidth, h: wEl.offsetHeight };
191
+ if (viewport.value.w && world.value.w) {
192
+ centered = true;
193
+ centerWorld();
194
+ }
195
+ });
196
+ onUnmounted(() => {
197
+ inertia.stop();
198
+ });
199
+ const transform = computed(
200
+ () => `translate(${tx.value}px, ${ty.value}px) scale(${scale.value})`
201
+ );
202
+ const cursor = computed(() => {
203
+ if (dragId !== null) return "grabbing";
204
+ if (spaceHeld.value) return "grab";
205
+ return "default";
206
+ });
207
+ defineExpose({
208
+ scale,
209
+ tx,
210
+ ty,
211
+ setScaleAt,
212
+ panBy,
213
+ resetView,
214
+ centerWorld
215
+ });
216
+ </script>
217
+
218
+ <template>
219
+ <div
220
+ ref="viewportEl"
221
+ class="zoomable-viewport"
222
+ :style="{ cursor }"
223
+ @wheel="onWheel"
224
+ @pointerdown="onPointerDown"
225
+ @pointermove="onPointerMove"
226
+ @pointerup="onPointerUp"
227
+ @pointercancel="onPointerUp"
228
+ @contextmenu.prevent
229
+ >
230
+ <div ref="worldEl" class="zoomable-world" :style="{ transform }">
231
+ <slot :scale="scale" :tx="tx" :ty="ty" />
232
+ </div>
233
+ </div>
234
+ </template>
235
+
236
+ <style scoped>
237
+ .zoomable-viewport{height:100%;overflow:hidden;position:relative;touch-action:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.zoomable-world{left:0;position:absolute;top:0;transform-origin:0 0;will-change:transform}
238
+ </style>
@@ -0,0 +1,48 @@
1
+ export interface ZoomableContainerProps {
2
+ minScale?: number;
3
+ maxScale?: number;
4
+ initialScale?: number;
5
+ zoomSpeed?: number;
6
+ wheelPanSpeed?: number;
7
+ }
8
+ declare function setScaleAt(target: number, px: number, py: number): void;
9
+ declare function panBy(dx: number, dy: number): void;
10
+ declare function centerWorld(): void;
11
+ declare function resetView(): void;
12
+ declare var __VLS_1: {
13
+ scale: number;
14
+ tx: number;
15
+ ty: number;
16
+ };
17
+ type __VLS_Slots = {} & {
18
+ default?: (props: typeof __VLS_1) => any;
19
+ };
20
+ declare const __VLS_base: import("vue").DefineComponent<ZoomableContainerProps, {
21
+ scale: import("vue").Ref<number, number>;
22
+ tx: import("vue").Ref<number, number>;
23
+ ty: import("vue").Ref<number, number>;
24
+ setScaleAt: typeof setScaleAt;
25
+ panBy: typeof panBy;
26
+ resetView: typeof resetView;
27
+ centerWorld: typeof centerWorld;
28
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
29
+ "update:scale": (value: number) => any;
30
+ "update:translate": (x: number, y: number) => any;
31
+ }, string, import("vue").PublicProps, Readonly<ZoomableContainerProps> & Readonly<{
32
+ "onUpdate:scale"?: ((value: number) => any) | undefined;
33
+ "onUpdate:translate"?: ((x: number, y: number) => any) | undefined;
34
+ }>, {
35
+ minScale: number;
36
+ maxScale: number;
37
+ initialScale: number;
38
+ zoomSpeed: number;
39
+ wheelPanSpeed: number;
40
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
42
+ declare const _default: typeof __VLS_export;
43
+ export default _default;
44
+ type __VLS_WithSlots<T, S> = T & {
45
+ new (): {
46
+ $slots: S;
47
+ };
48
+ };
@@ -157,5 +157,5 @@ onMounted(() => {
157
157
  </template>
158
158
 
159
159
  <style scoped>
160
- .carousel-wrapper{display:block;position:relative}.carousel-measure{height:v-bind(measureHeight);left:-9999px;pointer-events:none;position:fixed;visibility:hidden;width:v-bind(measureWidth)}.carousel-measure :deep(>*){display:block;height:100%;width:100%}.carousel{border:1px solid var(--color-border);border-radius:var(--border-radius-lg);height:v-bind("calculatedSize.height");max-height:v-bind(maxHeight);max-width:100%;overflow:hidden;transition:width .3s ease,height .3s ease;width:v-bind("calculatedSize.width")}.carousel-track{align-items:center;cursor:grab;display:flex;gap:.75rem;height:100%;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.carousel-track:active{cursor:grabbing}.carousel-item{background:var(--color-surface);border-radius:var(--border-radius-sm);color:var(--color-text);height:100%;inset:0;opacity:0;overflow:hidden;padding:.5rem .75rem;pointer-events:none;position:absolute;transition:opacity .5s ease-in-out,transform .5s ease-in-out;white-space:nowrap;width:100%}.carousel-item.previous-image{transform:translateX(-100%)}.carousel-item.next-image{transform:translateX(100%)}.carousel-item.active-image{opacity:1;pointer-events:auto;transform:translateX(0)}.carousel-item :deep(>*){height:100%;-o-object-fit:v-bind(fit);object-fit:v-bind(fit);width:100%}.carousel-empty{color:var(--color-muted)}.switch-button{position:absolute}.switch-button :deep(button){background:transparent!important;border:none!important;color:transparent!important}.switch-button :deep(button:hover){color:transparent!important}.switch-button :deep(.orio-icon){color:#fff!important;fill:#fff!important;filter:drop-shadow(0 0 2px rgba(0,0,0,.8)) drop-shadow(0 0 4px rgba(0,0,0,.6))}@supports (mix-blend-mode:difference) and (not (-webkit-hyphens:none)){.switch-button :deep(.orio-icon){color:#000!important;fill:#000!important;filter:grayscale(1) contrast(9) invert(1) drop-shadow(0 0 1px black) drop-shadow(0 0 2px black);mix-blend-mode:difference}}.switch-button.previous-button{left:0}.switch-button.next-button{right:0}.carousel--minimal{background:none;border:none}.carousel--minimal .carousel-item{background:none}.carousel--minimal .switch-button{opacity:0;transition:opacity .2s ease}.carousel--minimal:hover .switch-button{opacity:1}
160
+ .carousel-wrapper{display:block;position:relative}.carousel-measure{height:v-bind(measureHeight);left:-9999px;pointer-events:none;position:fixed;visibility:hidden;width:v-bind(measureWidth)}.carousel-measure :deep(>*){display:block;height:100%;width:100%}.carousel{border:1px solid var(--color-border);border-radius:var(--border-radius-lg);height:v-bind("calculatedSize.height");max-height:v-bind(maxHeight);max-width:100%;overflow:hidden;transition:width .3s ease,height .3s ease;width:v-bind("calculatedSize.width")}.carousel-track{align-items:center;cursor:grab;display:flex;gap:.75rem;height:100%;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.carousel-track:active{cursor:grabbing}.carousel-item{background:var(--color-surface);border-radius:var(--border-radius-sm);color:var(--color-text);height:100%;inset:0;opacity:0;overflow:hidden;padding:.5rem .75rem;pointer-events:none;position:absolute;transition:opacity .5s ease-in-out,transform .5s ease-in-out;white-space:nowrap;width:100%}.carousel-item.previous-image{transform:translateX(-100%)}.carousel-item.next-image{transform:translateX(100%)}.carousel-item.active-image{opacity:1;pointer-events:auto;transform:translateX(0)}.carousel-item :deep(>*){height:100%;-o-object-fit:v-bind(fit);object-fit:v-bind(fit);width:100%}.carousel-empty{color:var(--color-muted)}.switch-button{position:absolute}.switch-button :deep(button){background:transparent!important;border:none!important;color:transparent!important}.switch-button :deep(button:hover){color:transparent!important}.switch-button :deep(.icon){color:#fff!important;fill:#fff!important;filter:drop-shadow(0 0 2px rgba(0,0,0,.8)) drop-shadow(0 0 4px rgba(0,0,0,.6))}@supports (mix-blend-mode:difference) and (not (-webkit-hyphens:none)){.switch-button :deep(.icon){color:#000!important;fill:#000!important;filter:grayscale(1) contrast(9) invert(1) drop-shadow(0 0 1px black) drop-shadow(0 0 2px black);mix-blend-mode:difference}}.switch-button.previous-button{left:0}.switch-button.next-button{right:0}.carousel--minimal{background:none;border:none}.carousel--minimal .carousel-item{background:none}.carousel--minimal .switch-button{opacity:0;transition:opacity .2s ease}.carousel--minimal:hover .switch-button{opacity:1}
161
161
  </style>
@@ -0,0 +1,31 @@
1
+ interface Props {
2
+ images?: string[];
3
+ fit?: "fill" | "cover" | "contain" | "scale-down";
4
+ }
5
+ type __VLS_Props = Props;
6
+ type __VLS_ModelProps = {
7
+ "activeImage"?: string;
8
+ };
9
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
+ declare var __VLS_1: {
11
+ image: string;
12
+ };
13
+ type __VLS_Slots = {} & {
14
+ image?: (props: typeof __VLS_1) => any;
15
+ };
16
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
17
+ "update:activeImage": (value: string | undefined) => any;
18
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
19
+ "onUpdate:activeImage"?: ((value: string | undefined) => any) | undefined;
20
+ }>, {
21
+ images: string[];
22
+ fit: "fill" | "cover" | "contain" | "scale-down";
23
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
25
+ declare const _default: typeof __VLS_export;
26
+ export default _default;
27
+ type __VLS_WithSlots<T, S> = T & {
28
+ new (): {
29
+ $slots: S;
30
+ };
31
+ };
@@ -0,0 +1,64 @@
1
+ <script setup>
2
+ import { toRefs } from "vue";
3
+ const props = defineProps({
4
+ images: { type: Array, required: false, default: () => [] },
5
+ fit: { type: String, required: false, default: "cover" }
6
+ });
7
+ const { images, fit } = toRefs(props);
8
+ const activeImage = defineModel("activeImage", { type: String });
9
+ </script>
10
+
11
+ <template>
12
+ <div v-if="images.length > 1" class="carousel-preview">
13
+ <button
14
+ v-for="(image, index) of images"
15
+ :key="image"
16
+ type="button"
17
+ class="preview-item"
18
+ :class="{ active: image === activeImage }"
19
+ :aria-pressed="image === activeImage"
20
+ :aria-label="`Show image ${index + 1} of ${images.length}`"
21
+ @click="activeImage = image"
22
+ >
23
+ <slot name="image" :image>
24
+ <img :src="image" alt="" draggable="false" />
25
+ </slot>
26
+ </button>
27
+ </div>
28
+ </template>
29
+
30
+ <style scoped>
31
+ .carousel-preview {
32
+ display: flex;
33
+ gap: 0.5rem;
34
+ overflow-x: auto;
35
+ padding: 0.25rem 0;
36
+ }
37
+
38
+ .preview-item {
39
+ flex-shrink: 0;
40
+ width: 3.5rem;
41
+ height: 3.5rem;
42
+ padding: 0;
43
+ border: 2px solid var(--color-border);
44
+ border-radius: var(--border-radius-md);
45
+ background: var(--color-surface);
46
+ cursor: pointer;
47
+ overflow: hidden;
48
+ opacity: 0.6;
49
+ transition: opacity 0.2s ease, border-color 0.2s ease;
50
+ }
51
+ .preview-item:hover {
52
+ opacity: 0.85;
53
+ }
54
+ .preview-item.active {
55
+ opacity: 1;
56
+ border-color: var(--color-accent);
57
+ }
58
+ .preview-item :deep(> *) {
59
+ width: 100%;
60
+ height: 100%;
61
+ object-fit: v-bind(fit);
62
+ display: block;
63
+ }
64
+ </style>
@@ -0,0 +1,31 @@
1
+ interface Props {
2
+ images?: string[];
3
+ fit?: "fill" | "cover" | "contain" | "scale-down";
4
+ }
5
+ type __VLS_Props = Props;
6
+ type __VLS_ModelProps = {
7
+ "activeImage"?: string;
8
+ };
9
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
+ declare var __VLS_1: {
11
+ image: string;
12
+ };
13
+ type __VLS_Slots = {} & {
14
+ image?: (props: typeof __VLS_1) => any;
15
+ };
16
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
17
+ "update:activeImage": (value: string | undefined) => any;
18
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
19
+ "onUpdate:activeImage"?: ((value: string | undefined) => any) | undefined;
20
+ }>, {
21
+ images: string[];
22
+ fit: "fill" | "cover" | "contain" | "scale-down";
23
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
25
+ declare const _default: typeof __VLS_export;
26
+ export default _default;
27
+ type __VLS_WithSlots<T, S> = T & {
28
+ new (): {
29
+ $slots: S;
30
+ };
31
+ };
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { computed, toRefs } from "vue";
3
+ import { useI18n } from "vue-i18n";
3
4
  const props = defineProps({
4
5
  dates: { type: Object, required: true },
5
6
  month: { type: Boolean, required: false },
@@ -7,15 +8,16 @@ const props = defineProps({
7
8
  type: { type: String, required: false, default: "italics" }
8
9
  });
9
10
  const { dates } = toRefs(props);
11
+ const { t, locale } = useI18n();
10
12
  function formatMonthYear(value) {
11
13
  if (!value) return "";
12
14
  if (!props.month)
13
- return new Intl.DateTimeFormat("en-US", {
15
+ return new Intl.DateTimeFormat(locale.value, {
14
16
  day: "numeric",
15
17
  month: "short",
16
18
  year: "numeric"
17
19
  }).format(new Date(value));
18
- return new Intl.DateTimeFormat("en-US", {
20
+ return new Intl.DateTimeFormat(locale.value, {
19
21
  month: "short",
20
22
  year: "numeric"
21
23
  }).format(new Date(value));
@@ -23,7 +25,7 @@ function formatMonthYear(value) {
23
25
  const startDate = computed(() => formatMonthYear(dates.value.startDate));
24
26
  const endDate = computed(() => {
25
27
  if (dates.value.endDate === void 0) return null;
26
- return dates.value.endDate !== null ? formatMonthYear(dates.value.endDate) : "Present";
28
+ return dates.value.endDate !== null ? formatMonthYear(dates.value.endDate) : t("dates.present");
27
29
  });
28
30
  </script>
29
31
 
@@ -0,0 +1,7 @@
1
+ export interface KeyBindsProps {
2
+ /** Backtick-delimited shortcut string, e.g. "`Ctrl` + `Z`" */
3
+ bind: string;
4
+ }
5
+ declare const __VLS_export: import("vue").DefineComponent<KeyBindsProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<KeyBindsProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
+ declare const _default: typeof __VLS_export;
7
+ export default _default;
@@ -0,0 +1,36 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ const props = defineProps({
4
+ bind: { type: String, required: true }
5
+ });
6
+ const segments = computed(() => {
7
+ const parts = [];
8
+ const re = /`([^`]+)`/g;
9
+ let last = 0;
10
+ let match;
11
+ while ((match = re.exec(props.bind)) !== null) {
12
+ if (match.index > last) {
13
+ parts.push({ type: "text", value: props.bind.slice(last, match.index) });
14
+ }
15
+ parts.push({ type: "key", value: match[1] });
16
+ last = match.index + match[0].length;
17
+ }
18
+ if (last < props.bind.length) {
19
+ parts.push({ type: "text", value: props.bind.slice(last) });
20
+ }
21
+ return parts;
22
+ });
23
+ </script>
24
+
25
+ <template>
26
+ <span class="keybinds">
27
+ <template v-for="(seg, i) in segments" :key="i">
28
+ <kbd v-if="seg.type === 'key'">{{ seg.value }}</kbd>
29
+ <span v-else class="separator">{{ seg.value }}</span>
30
+ </template>
31
+ </span>
32
+ </template>
33
+
34
+ <style scoped>
35
+ .keybinds{font-size:var(--font-sm);gap:.2rem}.keybinds,kbd{align-items:center;display:inline-flex}kbd{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);border-radius:var(--border-radius-sm,4px);font-family:inherit;font-weight:500;justify-content:center;line-height:1.4;min-width:1.25em;padding:.1rem .35rem}.separator,kbd{font-size:.75rem}.separator{opacity:.6}
36
+ </style>
@@ -0,0 +1,7 @@
1
+ export interface KeyBindsProps {
2
+ /** Backtick-delimited shortcut string, e.g. "`Ctrl` + `Z`" */
3
+ bind: string;
4
+ }
5
+ declare const __VLS_export: import("vue").DefineComponent<KeyBindsProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<KeyBindsProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
+ declare const _default: typeof __VLS_export;
7
+ export default _default;
@@ -39,19 +39,19 @@ div.uppercase {
39
39
  text-transform: uppercase;
40
40
  }
41
41
  div.text {
42
- color: var(--color-text);
42
+ color: var(--view-text-color, var(--color-text));
43
43
  }
44
44
  div.title {
45
45
  font-weight: bold;
46
- color: var(--color-text);
46
+ color: var(--view-text-color, var(--color-text));
47
47
  }
48
48
  div.subtitle {
49
49
  font-weight: semi-bold;
50
- color: var(--color-muted);
50
+ color: var(--view-text-color, var(--color-muted));
51
51
  }
52
52
  div.italics {
53
53
  font-style: italic;
54
- color: var(--color-muted);
54
+ color: var(--view-text-color, var(--color-muted));
55
55
  }
56
56
  div.small {
57
57
  font-size: var(--font-sm);
@@ -0,0 +1,10 @@
1
+ export interface UseInertiaOptions {
2
+ friction?: number;
3
+ minVelocity?: number;
4
+ }
5
+ export declare function useInertia(onTick: (dx: number, dy: number) => void, options?: UseInertiaOptions): {
6
+ stop: () => void;
7
+ trackMove: (dx: number, dy: number) => void;
8
+ resetTime: () => void;
9
+ release: () => void;
10
+ };
@@ -0,0 +1,49 @@
1
+ export function useInertia(onTick, options = {}) {
2
+ const { friction = 0.92, minVelocity = 0.5 } = options;
3
+ let vx = 0;
4
+ let vy = 0;
5
+ let frameId = null;
6
+ let lastMoveTime = 0;
7
+ function tick() {
8
+ vx *= friction;
9
+ vy *= friction;
10
+ if (Math.abs(vx) < minVelocity && Math.abs(vy) < minVelocity) {
11
+ frameId = null;
12
+ return;
13
+ }
14
+ onTick(vx, vy);
15
+ frameId = requestAnimationFrame(tick);
16
+ }
17
+ function stop() {
18
+ if (frameId !== null) {
19
+ cancelAnimationFrame(frameId);
20
+ frameId = null;
21
+ }
22
+ vx = 0;
23
+ vy = 0;
24
+ }
25
+ function trackMove(dx, dy) {
26
+ const now = performance.now();
27
+ const dt = now - lastMoveTime;
28
+ lastMoveTime = now;
29
+ if (dt > 0 && dt < 100) {
30
+ const factor = 16 / dt;
31
+ vx = dx * factor;
32
+ vy = dy * factor;
33
+ } else {
34
+ vx = 0;
35
+ vy = 0;
36
+ }
37
+ }
38
+ function resetTime() {
39
+ lastMoveTime = performance.now();
40
+ }
41
+ function release() {
42
+ if (performance.now() - lastMoveTime < 50) {
43
+ if (Math.abs(vx) >= minVelocity || Math.abs(vy) >= minVelocity) {
44
+ frameId = requestAnimationFrame(tick);
45
+ }
46
+ }
47
+ }
48
+ return { stop, trackMove, resetTime, release };
49
+ }
@@ -0,0 +1,13 @@
1
+ export interface PinchCallbacks {
2
+ onPinchStart?: () => void;
3
+ onPinchMove?: (scaleFactor: number, midX: number, midY: number, dx: number, dy: number) => void;
4
+ onSingleDown?: (e: PointerEvent) => void;
5
+ onSingleUp?: (remainingId: number, x: number, y: number) => void;
6
+ onAllUp?: () => void;
7
+ }
8
+ export declare function usePinchZoom(callbacks: PinchCallbacks): {
9
+ onPointerDown: (e: PointerEvent) => boolean;
10
+ onPointerMove: (e: PointerEvent) => boolean;
11
+ onPointerUp: (e: PointerEvent) => boolean;
12
+ pointers: any;
13
+ };
@@ -0,0 +1,66 @@
1
+ export function usePinchZoom(callbacks) {
2
+ const pointers = /* @__PURE__ */ new Map();
3
+ let startDist = 0;
4
+ let lastMid = { x: 0, y: 0 };
5
+ function distance() {
6
+ const pts = [...pointers.values()];
7
+ if (pts.length < 2) return 0;
8
+ return Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y);
9
+ }
10
+ function midpoint() {
11
+ const pts = [...pointers.values()];
12
+ if (pts.length < 2) return { x: 0, y: 0 };
13
+ return {
14
+ x: (pts[0].x + pts[1].x) / 2,
15
+ y: (pts[0].y + pts[1].y) / 2
16
+ };
17
+ }
18
+ function onPointerDown(e) {
19
+ if (e.pointerType !== "touch") return false;
20
+ if (pointers.size >= 2) return false;
21
+ pointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
22
+ e.currentTarget.setPointerCapture(e.pointerId);
23
+ if (pointers.size === 2) {
24
+ startDist = distance();
25
+ lastMid = midpoint();
26
+ callbacks.onPinchStart?.();
27
+ return true;
28
+ }
29
+ if (pointers.size === 1) {
30
+ callbacks.onSingleDown?.(e);
31
+ return true;
32
+ }
33
+ return true;
34
+ }
35
+ function onPointerMove(e) {
36
+ if (!pointers.has(e.pointerId)) return false;
37
+ pointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
38
+ if (pointers.size === 2) {
39
+ const dist = distance();
40
+ const mid = midpoint();
41
+ const scaleFactor = startDist > 0 ? dist / startDist : 1;
42
+ const dx = mid.x - lastMid.x;
43
+ const dy = mid.y - lastMid.y;
44
+ lastMid = mid;
45
+ callbacks.onPinchMove?.(scaleFactor, mid.x, mid.y, dx, dy);
46
+ return true;
47
+ }
48
+ return false;
49
+ }
50
+ function onPointerUp(e) {
51
+ if (!pointers.has(e.pointerId)) return false;
52
+ pointers.delete(e.pointerId);
53
+ if (pointers.size === 1) {
54
+ const [id, pt] = [...pointers.entries()][0];
55
+ startDist = 0;
56
+ callbacks.onSingleUp?.(id, pt.x, pt.y);
57
+ return true;
58
+ }
59
+ if (pointers.size === 0) {
60
+ startDist = 0;
61
+ callbacks.onAllUp?.();
62
+ }
63
+ return false;
64
+ }
65
+ return { onPointerDown, onPointerMove, onPointerUp, pointers };
66
+ }