orio-ui 1.20.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 (139) 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/Canvas/REQUIREMENTS.md +174 -0
  7. package/dist/runtime/components/Canvas/components/Stage.d.vue.ts +3 -0
  8. package/dist/runtime/components/Canvas/components/Stage.vue +150 -0
  9. package/dist/runtime/components/Canvas/components/Stage.vue.d.ts +3 -0
  10. package/dist/runtime/components/Canvas/components/ToolButton.d.vue.ts +24 -0
  11. package/dist/runtime/components/Canvas/components/ToolButton.vue +62 -0
  12. package/dist/runtime/components/Canvas/components/ToolButton.vue.d.ts +24 -0
  13. package/dist/runtime/components/Canvas/components/Toolbar.d.vue.ts +24 -0
  14. package/dist/runtime/components/Canvas/components/Toolbar.vue +48 -0
  15. package/dist/runtime/components/Canvas/components/Toolbar.vue.d.ts +24 -0
  16. package/dist/runtime/components/Canvas/composables/useCanvasHistory.d.ts +17 -0
  17. package/dist/runtime/components/Canvas/composables/useCanvasHistory.js +76 -0
  18. package/dist/runtime/components/Canvas/composables/useCanvasNodes.d.ts +13 -0
  19. package/dist/runtime/components/Canvas/composables/useCanvasNodes.js +60 -0
  20. package/dist/runtime/components/Canvas/composables/useCanvasSetup.d.ts +5 -0
  21. package/dist/runtime/components/Canvas/composables/useCanvasSetup.js +19 -0
  22. package/dist/runtime/components/Canvas/context.d.ts +38 -0
  23. package/dist/runtime/components/Canvas/context.js +11 -0
  24. package/dist/runtime/components/Canvas/index.d.vue.ts +77 -0
  25. package/dist/runtime/components/Canvas/index.vue +208 -0
  26. package/dist/runtime/components/Canvas/index.vue.d.ts +77 -0
  27. package/dist/runtime/components/Canvas/registry.d.ts +1 -0
  28. package/dist/runtime/components/Canvas/registry.js +2 -0
  29. package/dist/runtime/components/Canvas/tools/ColorPickerWidget.d.vue.ts +7 -0
  30. package/dist/runtime/components/Canvas/tools/ColorPickerWidget.vue +32 -0
  31. package/dist/runtime/components/Canvas/tools/ColorPickerWidget.vue.d.ts +7 -0
  32. package/dist/runtime/components/Canvas/tools/clearTool.d.ts +1 -0
  33. package/dist/runtime/components/Canvas/tools/clearTool.js +16 -0
  34. package/dist/runtime/components/Canvas/tools/colorPickerTool.d.ts +6 -0
  35. package/dist/runtime/components/Canvas/tools/colorPickerTool.js +15 -0
  36. package/dist/runtime/components/Canvas/tools/drawTool.d.ts +16 -0
  37. package/dist/runtime/components/Canvas/tools/drawTool.js +92 -0
  38. package/dist/runtime/components/Canvas/tools/eraseTool.d.ts +5 -0
  39. package/dist/runtime/components/Canvas/tools/eraseTool.js +62 -0
  40. package/dist/runtime/components/Canvas/tools/exportTool.d.ts +18 -0
  41. package/dist/runtime/components/Canvas/tools/exportTool.js +89 -0
  42. package/dist/runtime/components/Canvas/tools/highlightTool.d.ts +11 -0
  43. package/dist/runtime/components/Canvas/tools/highlightTool.js +51 -0
  44. package/dist/runtime/components/Canvas/tools/hitTest.d.ts +20 -0
  45. package/dist/runtime/components/Canvas/tools/hitTest.js +111 -0
  46. package/dist/runtime/components/Canvas/tools/imageTool.d.ts +18 -0
  47. package/dist/runtime/components/Canvas/tools/imageTool.js +163 -0
  48. package/dist/runtime/components/Canvas/tools/moveTool.d.ts +5 -0
  49. package/dist/runtime/components/Canvas/tools/moveTool.js +94 -0
  50. package/dist/runtime/components/Canvas/tools/redoTool.d.ts +1 -0
  51. package/dist/runtime/components/Canvas/tools/redoTool.js +17 -0
  52. package/dist/runtime/components/Canvas/tools/resizeTool.d.ts +7 -0
  53. package/dist/runtime/components/Canvas/tools/resizeTool.js +132 -0
  54. package/dist/runtime/components/Canvas/tools/rotateTool.d.ts +5 -0
  55. package/dist/runtime/components/Canvas/tools/rotateTool.js +109 -0
  56. package/dist/runtime/components/Canvas/tools/textTool.d.ts +14 -0
  57. package/dist/runtime/components/Canvas/tools/textTool.js +99 -0
  58. package/dist/runtime/components/Canvas/tools/tooltips/Clear.d.vue.ts +3 -0
  59. package/dist/runtime/components/Canvas/tools/tooltips/Clear.vue +12 -0
  60. package/dist/runtime/components/Canvas/tools/tooltips/Clear.vue.d.ts +3 -0
  61. package/dist/runtime/components/Canvas/tools/tooltips/Draw.d.vue.ts +3 -0
  62. package/dist/runtime/components/Canvas/tools/tooltips/Draw.vue +12 -0
  63. package/dist/runtime/components/Canvas/tools/tooltips/Draw.vue.d.ts +3 -0
  64. package/dist/runtime/components/Canvas/tools/tooltips/Erase.d.vue.ts +3 -0
  65. package/dist/runtime/components/Canvas/tools/tooltips/Erase.vue +12 -0
  66. package/dist/runtime/components/Canvas/tools/tooltips/Erase.vue.d.ts +3 -0
  67. package/dist/runtime/components/Canvas/tools/tooltips/Export.d.vue.ts +3 -0
  68. package/dist/runtime/components/Canvas/tools/tooltips/Export.vue +13 -0
  69. package/dist/runtime/components/Canvas/tools/tooltips/Export.vue.d.ts +3 -0
  70. package/dist/runtime/components/Canvas/tools/tooltips/Highlight.d.vue.ts +3 -0
  71. package/dist/runtime/components/Canvas/tools/tooltips/Highlight.vue +12 -0
  72. package/dist/runtime/components/Canvas/tools/tooltips/Highlight.vue.d.ts +3 -0
  73. package/dist/runtime/components/Canvas/tools/tooltips/Image.d.vue.ts +3 -0
  74. package/dist/runtime/components/Canvas/tools/tooltips/Image.vue +13 -0
  75. package/dist/runtime/components/Canvas/tools/tooltips/Image.vue.d.ts +3 -0
  76. package/dist/runtime/components/Canvas/tools/tooltips/Move.d.vue.ts +3 -0
  77. package/dist/runtime/components/Canvas/tools/tooltips/Move.vue +13 -0
  78. package/dist/runtime/components/Canvas/tools/tooltips/Move.vue.d.ts +3 -0
  79. package/dist/runtime/components/Canvas/tools/tooltips/Redo.d.vue.ts +3 -0
  80. package/dist/runtime/components/Canvas/tools/tooltips/Redo.vue +13 -0
  81. package/dist/runtime/components/Canvas/tools/tooltips/Redo.vue.d.ts +3 -0
  82. package/dist/runtime/components/Canvas/tools/tooltips/Resize.d.vue.ts +3 -0
  83. package/dist/runtime/components/Canvas/tools/tooltips/Resize.vue +13 -0
  84. package/dist/runtime/components/Canvas/tools/tooltips/Resize.vue.d.ts +3 -0
  85. package/dist/runtime/components/Canvas/tools/tooltips/Rotate.d.vue.ts +3 -0
  86. package/dist/runtime/components/Canvas/tools/tooltips/Rotate.vue +13 -0
  87. package/dist/runtime/components/Canvas/tools/tooltips/Rotate.vue.d.ts +3 -0
  88. package/dist/runtime/components/Canvas/tools/tooltips/Text.d.vue.ts +3 -0
  89. package/dist/runtime/components/Canvas/tools/tooltips/Text.vue +13 -0
  90. package/dist/runtime/components/Canvas/tools/tooltips/Text.vue.d.ts +3 -0
  91. package/dist/runtime/components/Canvas/tools/tooltips/Transform.d.vue.ts +3 -0
  92. package/dist/runtime/components/Canvas/tools/tooltips/Transform.vue +14 -0
  93. package/dist/runtime/components/Canvas/tools/tooltips/Transform.vue.d.ts +3 -0
  94. package/dist/runtime/components/Canvas/tools/tooltips/Undo.d.vue.ts +3 -0
  95. package/dist/runtime/components/Canvas/tools/tooltips/Undo.vue +13 -0
  96. package/dist/runtime/components/Canvas/tools/tooltips/Undo.vue.d.ts +3 -0
  97. package/dist/runtime/components/Canvas/tools/transformHandles.d.ts +74 -0
  98. package/dist/runtime/components/Canvas/tools/transformHandles.js +191 -0
  99. package/dist/runtime/components/Canvas/tools/transformTool.d.ts +7 -0
  100. package/dist/runtime/components/Canvas/tools/transformTool.js +210 -0
  101. package/dist/runtime/components/Canvas/tools/undoTool.d.ts +1 -0
  102. package/dist/runtime/components/Canvas/tools/undoTool.js +17 -0
  103. package/dist/runtime/components/Canvas/types.d.ts +125 -0
  104. package/dist/runtime/components/Canvas/types.js +3 -0
  105. package/dist/runtime/components/ControlElement.vue +5 -1
  106. package/dist/runtime/components/DateRangePicker.vue +16 -4
  107. package/dist/runtime/components/Icon.vue +2 -2
  108. package/dist/runtime/components/LocaleSwitcher.d.vue.ts +13 -0
  109. package/dist/runtime/components/LocaleSwitcher.vue +43 -0
  110. package/dist/runtime/components/LocaleSwitcher.vue.d.ts +13 -0
  111. package/dist/runtime/components/Selector.vue +14 -5
  112. package/dist/runtime/components/Tooltip.vue +17 -7
  113. package/dist/runtime/components/ZoomableContainer.d.vue.ts +48 -0
  114. package/dist/runtime/components/ZoomableContainer.vue +238 -0
  115. package/dist/runtime/components/ZoomableContainer.vue.d.ts +48 -0
  116. package/dist/runtime/components/gallery/Carousel.vue +1 -1
  117. package/dist/runtime/components/gallery/CarouselPreview.d.vue.ts +31 -0
  118. package/dist/runtime/components/gallery/CarouselPreview.vue +64 -0
  119. package/dist/runtime/components/gallery/CarouselPreview.vue.d.ts +31 -0
  120. package/dist/runtime/components/view/Dates.vue +5 -3
  121. package/dist/runtime/components/view/KeyBinds.d.vue.ts +7 -0
  122. package/dist/runtime/components/view/KeyBinds.vue +36 -0
  123. package/dist/runtime/components/view/KeyBinds.vue.d.ts +7 -0
  124. package/dist/runtime/components/view/Text.vue +4 -4
  125. package/dist/runtime/composables/useInertia.d.ts +10 -0
  126. package/dist/runtime/composables/useInertia.js +49 -0
  127. package/dist/runtime/composables/usePinchZoom.d.ts +13 -0
  128. package/dist/runtime/composables/usePinchZoom.js +66 -0
  129. package/dist/runtime/composables/useValidation.js +11 -1
  130. package/dist/runtime/i18n/en.json +20 -0
  131. package/dist/runtime/i18n/index.d.ts +11 -0
  132. package/dist/runtime/i18n/index.js +19 -0
  133. package/dist/runtime/i18n/uk.json +20 -0
  134. package/dist/runtime/index.d.ts +5 -0
  135. package/dist/runtime/index.js +16 -0
  136. package/dist/runtime/plugins/i18n.d.ts +2 -0
  137. package/dist/runtime/plugins/i18n.js +18 -0
  138. package/dist/runtime/utils/icon-registry.js +13 -1
  139. package/package.json +9 -4
@@ -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
+ };
@@ -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
+ };