@getdom/studio 0.1.1 → 0.2.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.
- package/CHANGELOG.md +31 -0
- package/README.md +31 -0
- package/SKILL.md +21 -1
- package/package.json +4 -2
- package/public/llms.txt +13 -2
- package/src/pages/_layout/componentCatalog.generated.js +1185 -44
- package/src/pages/_layout/componentLoaders.js +41 -0
- package/src/pages/_layout/componentManager.js +38 -27
- package/src/pages/_layout/componentRuntimeRecords.js +3 -1
- package/src/pages/charts/_shared/ChartContainer.vue +67 -0
- package/src/pages/charts/_shared/ChartLegend.vue +22 -0
- package/src/pages/charts/_shared/ChartTooltip.vue +18 -0
- package/src/pages/charts/_shared/DonutRenderer.vue +33 -0
- package/src/pages/charts/_shared/XYChart.vue +140 -0
- package/src/pages/charts/_shared/XYRenderer.vue +90 -0
- package/src/pages/charts/_shared/chartProps.js +23 -0
- package/src/pages/charts/_shared/chartUtils.js +95 -0
- package/src/pages/charts/area-chart/DomAreaChart.vue +27 -0
- package/src/pages/charts/bar-chart/DomBarChart.vue +29 -0
- package/src/pages/charts/date-range-picker/DomDateRangePicker.vue +104 -0
- package/src/pages/charts/date-range-picker/dateRange.js +69 -0
- package/src/pages/charts/donut-chart/DomDonutChart.vue +117 -0
- package/src/pages/charts/line-chart/DomLineChart.vue +26 -0
- package/src/pages/charts/metric-card/DomMetricCard.vue +49 -0
- package/src/pages/charts/sparkline/DomSparkline.vue +30 -0
- package/src/pages/components/_shared/media/MediaDeviceSelect.vue +28 -0
- package/src/pages/components/_shared/media/useMediaInput.js +200 -0
- package/src/pages/components/audio-controls/DomAudioControls.vue +91 -0
- package/src/pages/components/audio-input/DomAudioInput.vue +58 -0
- package/src/pages/components/button/DomButton.vue +10 -4
- package/src/pages/components/button/buttonStyles.js +5 -0
- package/src/pages/components/camera-input/DomCameraInput.vue +75 -0
- package/src/pages/components/command-palette/DomCommandPalette.vue +12 -2
- package/src/pages/components/dialog/DomDialog.vue +338 -36
- package/src/pages/components/icon-button/DomIconButton.vue +8 -2
- package/src/pages/components/menu-stack/DomMenuStack.vue +111 -0
- package/src/pages/components/menu-stack/menuTree.js +35 -0
- package/src/pages/components/popover/DomPopover.vue +1 -53
- package/src/pages/components/popover/popover.css +50 -0
- package/src/pages/components/video-feed/DomVideoFeed.vue +551 -0
- package/src/pages/data/agent-chat/DomAgentChatShell.vue +1 -0
- package/src/pages/data/agent-chat/DomAgentConversation.vue +1 -0
- package/src/pages/data/agent-chat/DomAgentConversationList.vue +1 -0
- package/src/pages/data/gantt/DomGantt.vue +788 -0
- package/src/pages/data/gantt/ganttTime.js +223 -0
- package/src/pages/data/month-calendar/DomMonthCalendar.vue +84 -9
- package/src/pages/data/notification-inbox/DomNotificationInbox.vue +505 -0
- package/src/pages/data/notification-inbox/notificationPresentation.js +34 -0
- package/src/pages/designer/_shared/ControlIconButton.vue +62 -0
- package/src/pages/designer/_shared/StyleControlSection.vue +59 -0
- package/src/pages/designer/_shared/cssEditorContext.js +19 -0
- package/src/pages/designer/backdrop-editor/BackdropControl.vue +57 -0
- package/src/pages/designer/backdrop-editor/DomBackdropEditor.vue +33 -0
- package/src/pages/designer/backdrop-editor/backdropModel.js +39 -0
- package/src/pages/designer/background-editor/BackgroundLayers.vue +210 -0
- package/src/pages/designer/background-editor/DomBackgroundEditor.vue +33 -0
- package/src/pages/designer/background-editor/backgroundModel.js +102 -0
- package/src/pages/designer/border-editor/BorderControl.vue +72 -0
- package/src/pages/designer/border-editor/DomBorderEditor.vue +34 -0
- package/src/pages/designer/border-editor/borderModel.js +21 -0
- package/src/pages/designer/color-swatch/DomColorSwatch.vue +95 -0
- package/src/pages/designer/frame/DomDesignerFrame.vue +16 -0
- package/src/pages/designer/frame/DomFrameLayoutEditor.vue +41 -0
- package/src/pages/designer/frame/frameLayout.js +93 -0
- package/src/pages/designer/layers/DomDesignerLayers.vue +11 -0
- package/src/pages/designer/shadow-editor/DomShadowEditor.vue +32 -0
- package/src/pages/designer/shadow-editor/ShadowLayers.vue +185 -0
- package/src/pages/designer/shadow-editor/shadowModel.js +73 -0
- package/src/pages/designer/stage/DesignerBounds.vue +31 -0
- package/src/pages/designer/stage/DomDesignerStage.vue +237 -0
- package/src/pages/designer/stage/SpacingGuides.vue +33 -0
- package/src/pages/designer/stage/resizeGeometry.js +15 -0
- package/src/pages/designer/stage/snapGeometry.js +69 -0
- package/src/pages/designer/stage/snapPipeline.js +17 -0
- package/src/pages/designer/stage/spacingGeometry.js +129 -0
- package/src/pages/forms/native-select/DomNativeSelect.vue +8 -3
- package/src/pages/forms/number-input/DomNumberInput.vue +39 -3
- package/src/pages/forms/range-input/DomRangeInput.vue +75 -23
- package/src/pages/forms/textarea-composer/DomTextareaComposer.vue +91 -9
- package/src/pages/forms/toggle/DomToggle.vue +1 -1
- package/src/pages/lib/headless/base.js +10 -5
- package/src/pages/lib/headless/dialog.js +25 -6
- package/src/pages/lib/headless/drawer.js +49 -21
- package/src/pages/lib/vue/index.d.ts +1161 -14
- package/src/pages/lib/vue/index.js +43 -0
- package/src/pages/mobile/_shared/interactionMath.js +46 -0
- package/src/pages/mobile/_shared/useKeyboardViewport.js +91 -0
- package/src/pages/mobile/action-sheet/DomActionSheet.vue +102 -65
- package/src/pages/mobile/bottom-nav/DomAppBottomNav.vue +4 -2
- package/src/pages/mobile/bottom-sheet/DomBottomSheet.vue +221 -0
- package/src/pages/mobile/list-item/DomAppListItem.vue +6 -6
- package/src/pages/mobile/profile/DomAppProfile.vue +42 -0
- package/src/pages/mobile/safe-area/DomSafeArea.vue +6 -6
- package/src/pages/mobile/shell/DomAppShell.vue +60 -9
- package/src/pages/mobile/stack/DomAppStack.vue +214 -55
- package/src/pages/mobile/swipe-actions/DomSwipeActions.vue +346 -0
- package/src/pages/mobile/top-bar/DomAppTopBar.vue +3 -3
- package/src/pages/visual/audio-visualizer/DomAudioVisualizer.vue +143 -0
- package/src/theme.css +13 -0
|
@@ -66,19 +66,27 @@ const DRAG_EXIT_MS = 170;
|
|
|
66
66
|
const DRAG_PROJECT_MS = 220;
|
|
67
67
|
const DRAG_FLICK_VELOCITY = 0.45;
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
69
|
+
const scrollLocks = new WeakMap();
|
|
70
|
+
|
|
71
|
+
/** Locks a scroll container while preserving its existing inline overflow. */
|
|
72
|
+
function lockBodyScroll(target) {
|
|
73
|
+
if (!target) return;
|
|
74
|
+
const lock = scrollLocks.get(target);
|
|
75
|
+
if (lock) lock.count += 1;
|
|
76
|
+
else {
|
|
77
|
+
scrollLocks.set(target, { count: 1, overflow: target.style.overflow });
|
|
78
|
+
target.style.overflow = 'hidden';
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/** Restores a container only after its last open drawer releases the lock. */
|
|
83
|
+
function unlockBodyScroll(target) {
|
|
84
|
+
const lock = target && scrollLocks.get(target);
|
|
85
|
+
if (!lock || --lock.count > 0) return;
|
|
86
|
+
target.style.overflow = lock.overflow;
|
|
87
|
+
scrollLocks.delete(target);
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
function wantsOpen(el) {
|
|
83
91
|
return el.boolAttr('open') || el.boolAttr('show');
|
|
84
92
|
}
|
|
@@ -117,6 +125,7 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
117
125
|
'leave-to',
|
|
118
126
|
'aria-labelledby',
|
|
119
127
|
'aria-describedby',
|
|
128
|
+
'aria-label',
|
|
120
129
|
];
|
|
121
130
|
}
|
|
122
131
|
|
|
@@ -140,6 +149,7 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
140
149
|
{ name: 'leave-to', type: 'string', description: 'Tailwind classes applied for the leave transition end state.' },
|
|
141
150
|
],
|
|
142
151
|
events: [
|
|
152
|
+
{ name: 'dom:state', description: 'Fired immediately when open state changes, with { open: boolean }, before animation completes.' },
|
|
143
153
|
{ name: 'dom:open', description: 'Fired when the drawer opens.' },
|
|
144
154
|
{ name: 'dom:close', description: 'Fired when the drawer closes (Esc, backdrop, data-close, or programmatic).' },
|
|
145
155
|
],
|
|
@@ -210,13 +220,17 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
210
220
|
if (wantsOpen(this)) this.open = true;
|
|
211
221
|
}
|
|
212
222
|
|
|
223
|
+
/** Cancels pending motion and releases document resources when removed or moved. */
|
|
213
224
|
disconnectedCallback() {
|
|
225
|
+
this._transitionGen += 1;
|
|
226
|
+
this._transitioning = false;
|
|
227
|
+
this._open = false;
|
|
214
228
|
this._finishDrag(false);
|
|
215
229
|
this._teardownDragHandle();
|
|
216
230
|
if (this._dragResetTimer) window.clearTimeout(this._dragResetTimer);
|
|
217
231
|
this._dragResetTimer = null;
|
|
218
232
|
this._unlockScroll();
|
|
219
|
-
|
|
233
|
+
this.ownerDocument.removeEventListener('keydown', this._onKey);
|
|
220
234
|
this._releaseFocus?.();
|
|
221
235
|
this._releaseFocus = null;
|
|
222
236
|
super.disconnectedCallback();
|
|
@@ -280,9 +294,10 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
280
294
|
});
|
|
281
295
|
}
|
|
282
296
|
|
|
297
|
+
/** Copies the accessible name and description onto the dialog panel. */
|
|
283
298
|
_syncAria() {
|
|
284
299
|
if (!this._panel) return;
|
|
285
|
-
for (const name of ['aria-labelledby', 'aria-describedby']) {
|
|
300
|
+
for (const name of ['aria-labelledby', 'aria-describedby', 'aria-label']) {
|
|
286
301
|
const value = this.getAttribute(name);
|
|
287
302
|
if (value) this._panel.setAttribute(name, value);
|
|
288
303
|
else this._panel.removeAttribute(name);
|
|
@@ -428,10 +443,10 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
428
443
|
? this._onDragTouchEnd
|
|
429
444
|
: this._onDragMouseUp;
|
|
430
445
|
this._dragOffs = [
|
|
431
|
-
this.on(
|
|
432
|
-
this.on(
|
|
446
|
+
this.on(this.ownerDocument, options.moveType, moveHandler, { passive: false }),
|
|
447
|
+
this.on(this.ownerDocument, options.upType, upHandler, { passive: false }),
|
|
433
448
|
];
|
|
434
|
-
if (options.cancelType) this._dragOffs.push(this.on(
|
|
449
|
+
if (options.cancelType) this._dragOffs.push(this.on(this.ownerDocument, options.cancelType, upHandler, { passive: false }));
|
|
435
450
|
e.preventDefault();
|
|
436
451
|
}
|
|
437
452
|
|
|
@@ -547,15 +562,19 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
547
562
|
if (this.hasAttribute('show')) this.setBoolAttr('show', next);
|
|
548
563
|
}
|
|
549
564
|
|
|
565
|
+
/** Locks the drawer document or its containing app scroll region. */
|
|
550
566
|
_lockScroll() {
|
|
551
567
|
if (this._scrollLocked) return;
|
|
552
|
-
|
|
568
|
+
this._scrollTarget = this.closest('[data-dom-app-shell]')?.querySelector('[data-dom-app-shell-main]') || this.ownerDocument.body;
|
|
569
|
+
lockBodyScroll(this._scrollTarget);
|
|
553
570
|
this._scrollLocked = true;
|
|
554
571
|
}
|
|
555
572
|
|
|
573
|
+
/** Releases this drawer scroll lock without disturbing other overlays. */
|
|
556
574
|
_unlockScroll() {
|
|
557
575
|
if (!this._scrollLocked) return;
|
|
558
|
-
unlockBodyScroll();
|
|
576
|
+
unlockBodyScroll(this._scrollTarget);
|
|
577
|
+
this._scrollTarget = null;
|
|
559
578
|
this._scrollLocked = false;
|
|
560
579
|
}
|
|
561
580
|
|
|
@@ -584,21 +603,27 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
584
603
|
this._overlay.setAttribute('aria-hidden', String(!open));
|
|
585
604
|
}
|
|
586
605
|
|
|
606
|
+
/** Traps keyboard focus within the newly opened panel. */
|
|
587
607
|
_finishOpen() {
|
|
608
|
+
this._releaseFocus?.();
|
|
588
609
|
this._releaseFocus = focusTrap(this._panel);
|
|
589
610
|
requestAnimationFrame(() => this._panel.focus({ preventScroll: true }));
|
|
590
611
|
this.emit('dom:open');
|
|
591
612
|
}
|
|
592
613
|
|
|
614
|
+
/** Restores scrolling and returns focus to the control that opened the drawer. */
|
|
593
615
|
_finishClose() {
|
|
594
616
|
this._unlockScroll();
|
|
595
|
-
|
|
617
|
+
this.ownerDocument.removeEventListener('keydown', this._onKey);
|
|
596
618
|
this._releaseFocus?.();
|
|
597
619
|
this._releaseFocus = null;
|
|
598
|
-
this.
|
|
620
|
+
const returnTarget = this._returnFocus || this._trigger;
|
|
621
|
+
if (returnTarget?.isConnected) returnTarget.focus({ preventScroll: true });
|
|
622
|
+
this._returnFocus = null;
|
|
599
623
|
this.emit('dom:close');
|
|
600
624
|
}
|
|
601
625
|
|
|
626
|
+
/** Synchronizes controlled open state, motion, focus, and scroll ownership. */
|
|
602
627
|
async _setOpen(next) {
|
|
603
628
|
if (!this._panel || !this._overlay) return;
|
|
604
629
|
if (next === this._open && !this._transitioning) return;
|
|
@@ -608,12 +633,14 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
608
633
|
this._syncMotionClasses();
|
|
609
634
|
|
|
610
635
|
if (next) {
|
|
636
|
+
this._returnFocus = this.ownerDocument.activeElement;
|
|
611
637
|
this._setupDragHandle();
|
|
612
638
|
this._open = true;
|
|
613
639
|
this._reflectOpen(true);
|
|
640
|
+
this.emit('dom:state', { open: true });
|
|
614
641
|
this._trigger?.setAttribute('aria-expanded', 'true');
|
|
615
642
|
this._lockScroll();
|
|
616
|
-
|
|
643
|
+
this.ownerDocument.addEventListener('keydown', this._onKey);
|
|
617
644
|
|
|
618
645
|
this._overlay.hidden = false;
|
|
619
646
|
if (custom) {
|
|
@@ -633,6 +660,7 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
633
660
|
} else {
|
|
634
661
|
this._open = false;
|
|
635
662
|
this._reflectOpen(false);
|
|
663
|
+
this.emit('dom:state', { open: false });
|
|
636
664
|
this._trigger?.setAttribute('aria-expanded', 'false');
|
|
637
665
|
|
|
638
666
|
if (custom) {
|
|
@@ -666,7 +694,7 @@ export class DomDrawerElement extends DomElementBase {
|
|
|
666
694
|
if (['enter', 'enter-from', 'enter-to', 'leave', 'leave-from', 'leave-to'].includes(name)) {
|
|
667
695
|
this._syncMotionClasses();
|
|
668
696
|
}
|
|
669
|
-
if (
|
|
697
|
+
if (['aria-labelledby', 'aria-describedby', 'aria-label'].includes(name)) this._syncAria();
|
|
670
698
|
}
|
|
671
699
|
|
|
672
700
|
get open() { return this._open; }
|