@motion-proto/live-tokens 0.1.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 (68) hide show
  1. package/README.md +41 -0
  2. package/dist-plugin/index.cjs +444 -0
  3. package/dist-plugin/index.d.cts +12 -0
  4. package/dist-plugin/index.d.ts +12 -0
  5. package/dist-plugin/index.js +407 -0
  6. package/package.json +86 -0
  7. package/src/components/Badge.svelte +82 -0
  8. package/src/components/Button.svelte +333 -0
  9. package/src/components/Card.svelte +83 -0
  10. package/src/components/CollapsibleSection.svelte +82 -0
  11. package/src/components/DetailNav.svelte +78 -0
  12. package/src/components/Dialog.svelte +269 -0
  13. package/src/components/InlineEditActions.svelte +73 -0
  14. package/src/components/Notification.svelte +308 -0
  15. package/src/components/ProgressBar.svelte +99 -0
  16. package/src/components/RadioButton.svelte +87 -0
  17. package/src/components/SectionDivider.svelte +121 -0
  18. package/src/components/TabBar.svelte +92 -0
  19. package/src/components/Toggle.svelte +86 -0
  20. package/src/components/Tooltip.svelte +64 -0
  21. package/src/lib/ColumnsOverlay.svelte +120 -0
  22. package/src/lib/LiveEditorOverlay.svelte +467 -0
  23. package/src/lib/columnsOverlay.ts +26 -0
  24. package/src/lib/cssVarSync.ts +72 -0
  25. package/src/lib/editorConfig.ts +9 -0
  26. package/src/lib/editorConfigStore.ts +14 -0
  27. package/src/lib/index.ts +51 -0
  28. package/src/lib/oklch.ts +129 -0
  29. package/src/lib/pageSource.ts +6 -0
  30. package/src/lib/tokenInit.ts +29 -0
  31. package/src/lib/tokenService.ts +144 -0
  32. package/src/lib/tokenTypes.ts +45 -0
  33. package/src/pages/Admin.svelte +100 -0
  34. package/src/pages/ShowcasePage.svelte +146 -0
  35. package/src/showcase/BackupBrowser.svelte +617 -0
  36. package/src/showcase/BezierCurveEditor.svelte +648 -0
  37. package/src/showcase/ColorEditPanel.svelte +498 -0
  38. package/src/showcase/ComponentsTab.svelte +107 -0
  39. package/src/showcase/EditorDialog.svelte +137 -0
  40. package/src/showcase/PaletteEditor.svelte +2579 -0
  41. package/src/showcase/PaletteSelector.svelte +627 -0
  42. package/src/showcase/SurfacesTab.svelte +409 -0
  43. package/src/showcase/TextTab.svelte +205 -0
  44. package/src/showcase/TokenFileManager.svelte +683 -0
  45. package/src/showcase/TokenMap.svelte +54 -0
  46. package/src/showcase/VariablesTab.svelte +2657 -0
  47. package/src/showcase/VisualsTab.svelte +233 -0
  48. package/src/showcase/curveEngine.ts +190 -0
  49. package/src/showcase/demos/BadgeDemo.svelte +58 -0
  50. package/src/showcase/demos/CardDemo.svelte +52 -0
  51. package/src/showcase/demos/ChoiceButtonsDemo.svelte +194 -0
  52. package/src/showcase/demos/CollapsibleSectionDemo.svelte +56 -0
  53. package/src/showcase/demos/DialogDemo.svelte +42 -0
  54. package/src/showcase/demos/InlineEditActionsDemo.svelte +27 -0
  55. package/src/showcase/demos/NotificationDemo.svelte +149 -0
  56. package/src/showcase/demos/ProgressBarDemo.svelte +56 -0
  57. package/src/showcase/demos/RadioButtonDemo.svelte +58 -0
  58. package/src/showcase/demos/SectionDividerDemo.svelte +79 -0
  59. package/src/showcase/demos/StandardButtonsDemo.svelte +457 -0
  60. package/src/showcase/demos/TabBarDemo.svelte +60 -0
  61. package/src/showcase/demos/TooltipDemo.svelte +54 -0
  62. package/src/showcase/editor.css +93 -0
  63. package/src/showcase/index.ts +17 -0
  64. package/src/styles/fonts/Domine/Domine-VariableFont_wght.ttf +0 -0
  65. package/src/styles/fonts/Domine/OFL.txt +97 -0
  66. package/src/styles/fonts/Domine/README.txt +66 -0
  67. package/src/styles/fonts.css +18 -0
  68. package/src/styles/form-controls.css +190 -0
@@ -0,0 +1,269 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher, tick } from 'svelte';
3
+
4
+ export let show: boolean = false;
5
+ export let title: string = '';
6
+ export let confirmLabel: string = 'Confirm';
7
+ export let cancelLabel: string = 'Cancel';
8
+ export let showConfirm: boolean = true;
9
+ export let showCancel: boolean = true;
10
+ export let confirmDisabled: boolean = false;
11
+ export let width: string = '500px';
12
+
13
+ // Optional callbacks for parent dialogs to control behavior
14
+ export let onConfirm: (() => void) | undefined = undefined;
15
+ export let onCancel: (() => void) | undefined = undefined;
16
+
17
+ const dispatch = createEventDispatcher<{
18
+ confirm: void;
19
+ cancel: void;
20
+ close: void;
21
+ }>();
22
+
23
+ // Reference to the primary (confirm) button for focus management
24
+ let confirmButtonRef: HTMLButtonElement;
25
+ let cancelButtonRef: HTMLButtonElement;
26
+ let closeButtonRef: HTMLButtonElement;
27
+
28
+ // Focus the primary button when dialog opens
29
+ $: if (show) {
30
+ tick().then(() => {
31
+ // Focus the primary (confirm) button first, then fall back to cancel, then close
32
+ if (showConfirm && confirmButtonRef && !confirmDisabled) {
33
+ confirmButtonRef.focus();
34
+ } else if (showCancel && cancelButtonRef) {
35
+ cancelButtonRef.focus();
36
+ } else if (closeButtonRef) {
37
+ closeButtonRef.focus();
38
+ }
39
+ });
40
+ }
41
+
42
+ function handleConfirm() {
43
+ if (!confirmDisabled) {
44
+ if (onConfirm) {
45
+ // Parent dialog controls the flow
46
+ onConfirm();
47
+ } else {
48
+ // Default behavior for backward compatibility
49
+ dispatch('confirm');
50
+ }
51
+ }
52
+ }
53
+
54
+ function handleCancel() {
55
+ if (onCancel) {
56
+ // Parent dialog controls the flow
57
+ onCancel();
58
+ } else {
59
+ // Default behavior for backward compatibility
60
+ dispatch('cancel');
61
+ dispatch('close');
62
+ show = false;
63
+ }
64
+ }
65
+
66
+ // No implicit keyboard or backdrop close handlers
67
+ // Dialog only closes via explicit button clicks (X, Cancel, or Confirm)
68
+ </script>
69
+
70
+ {#if show}
71
+ <div class="dialog-backdrop">
72
+ <div class="dialog" style="width: {width}; max-width: {width};">
73
+ <div class="dialog-content">
74
+ {#if title}
75
+ <div class="dialog-header">
76
+ <h3 class="dialog-title">{title}</h3>
77
+ <button
78
+ bind:this={closeButtonRef}
79
+ class="dialog-close"
80
+ on:click={handleCancel}
81
+ aria-label="Close"
82
+ tabindex="0"
83
+ >
84
+ <i class="fas fa-times"></i>
85
+ </button>
86
+ </div>
87
+ {/if}
88
+
89
+ <div class="dialog-body">
90
+ <slot />
91
+ </div>
92
+
93
+ {#if showConfirm || showCancel}
94
+ <div class="dialog-footer">
95
+ <div class="dialog-footer-left">
96
+ <slot name="footer-left" />
97
+ </div>
98
+ <div class="dialog-footer-buttons">
99
+ {#if showCancel}
100
+ <button
101
+ bind:this={cancelButtonRef}
102
+ class="dialog-button dialog-button-secondary"
103
+ on:click={handleCancel}
104
+ tabindex="0"
105
+ >
106
+ {cancelLabel}
107
+ </button>
108
+ {/if}
109
+ {#if showConfirm}
110
+ <button
111
+ bind:this={confirmButtonRef}
112
+ class="dialog-button dialog-button-primary"
113
+ on:click={handleConfirm}
114
+ disabled={confirmDisabled}
115
+ tabindex="0"
116
+ >
117
+ {confirmLabel}
118
+ </button>
119
+ {/if}
120
+ </div>
121
+ </div>
122
+ {/if}
123
+ </div>
124
+ </div>
125
+ </div>
126
+ {/if}
127
+
128
+ <style>
129
+ .dialog-backdrop {
130
+ position: fixed;
131
+ top: 0;
132
+ left: 0;
133
+ width: 100%;
134
+ height: 100%;
135
+ background-color: var(--overlay-high);
136
+ display: flex;
137
+ justify-content: center;
138
+ align-items: center;
139
+ z-index: var(--z-overlay);
140
+ pointer-events: auto;
141
+ }
142
+
143
+ .dialog {
144
+ background: var(--surface-neutral-lowest);
145
+ border: 2px solid var(--border-neutral-strong);
146
+ border-radius: var(--radius-lg);
147
+ box-shadow: var(--shadow-overlay);
148
+ animation: dialogSlideIn var(--transition-base);
149
+ pointer-events: auto;
150
+ }
151
+
152
+ @keyframes dialogSlideIn {
153
+ from {
154
+ opacity: 0;
155
+ transform: translateY(-1.25rem);
156
+ }
157
+ to {
158
+ opacity: 1;
159
+ transform: translateY(0);
160
+ }
161
+ }
162
+
163
+ .dialog-content {
164
+ padding: 0;
165
+ }
166
+
167
+ .dialog-header {
168
+ padding: .5rem var(--space-24);
169
+ border-bottom: 1px solid var(--border-neutral-subtle);
170
+ background: var(--empty);
171
+ display: flex;
172
+ justify-content: space-between;
173
+ align-items: center;
174
+ }
175
+
176
+ .dialog-title {
177
+ margin: 0;
178
+ font-size: var(--font-2xl);
179
+ font-weight: var(--font-weight-semibold);
180
+ color: var(--text-primary);
181
+ }
182
+
183
+ .dialog-close {
184
+ background: none;
185
+ border: none;
186
+ color: var(--text-secondary);
187
+ font-size: var(--font-xl);
188
+ cursor: pointer;
189
+ margin-right: -var(--space-16);
190
+ width: 2rem;
191
+ height: 2rem;
192
+ display: flex;
193
+ align-items: center;
194
+ justify-content: center;
195
+ border-radius: var(--radius-md);
196
+ transition: all var(--transition-base);
197
+ }
198
+
199
+ .dialog-close:hover {
200
+ background: var(--hover);
201
+ color: var(--text-primary);
202
+ }
203
+
204
+ .dialog-body {
205
+ padding: var(--space-16) var(--space-24);
206
+ }
207
+
208
+ .dialog-footer {
209
+ padding: var(--space-16);
210
+ border-top: 1px solid var(--border-neutral-subtle);
211
+ display: flex;
212
+ justify-content: space-between;
213
+ align-items: center;
214
+ gap: var(--space-16);
215
+ }
216
+
217
+ .dialog-footer-left {
218
+ display: flex;
219
+ align-items: center;
220
+ }
221
+
222
+ .dialog-footer-buttons {
223
+ display: flex;
224
+ gap: var(--space-8);
225
+ }
226
+
227
+ .dialog-button {
228
+ padding: var(--space-8) var(--space-16);
229
+ border: 1px solid var(--border-neutral-subtle);
230
+ border-radius: var(--radius-md);
231
+ font-size: var(--font-md);
232
+ font-weight: var(--font-weight-medium);
233
+ cursor: pointer;
234
+ transition: all var(--transition-base);
235
+ min-width: 5rem;
236
+ }
237
+
238
+ .dialog-button:disabled {
239
+ opacity: var(--opacity-disabled);
240
+ cursor: not-allowed;
241
+ }
242
+
243
+ .dialog-button-primary {
244
+ background: var(--btn-secondary-bg);
245
+ color: var(--text-primary);
246
+ border-color: var(--border-neutral-medium);
247
+ }
248
+
249
+ .dialog-button-primary:hover:not(:disabled) {
250
+ background: var(--btn-secondary-hover);
251
+ border-color: var(--border-neutral-strong);
252
+ }
253
+
254
+ .dialog-button-primary:focus {
255
+ outline: 2px solid var(--border-neutral-strong);
256
+ outline-offset: 0.125rem;
257
+ }
258
+
259
+ .dialog-button-secondary {
260
+ background: transparent;
261
+ color: var(--text-primary);
262
+ border-color: var(--border-neutral-medium);
263
+ }
264
+
265
+ .dialog-button-secondary:hover:not(:disabled) {
266
+ background: var(--hover-low);
267
+ border-color: var(--border-neutral-strong);
268
+ }
269
+ </style>
@@ -0,0 +1,73 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Reusable inline edit action buttons (confirm/cancel)
4
+ * Used for inline editing throughout the app
5
+ */
6
+
7
+ export let onSave: () => void | Promise<void>;
8
+ export let onCancel: () => void;
9
+ export let disabled = false;
10
+ export let saveTitle = "Save";
11
+ export let cancelTitle = "Cancel";
12
+ </script>
13
+
14
+ <div class="inline-actions">
15
+ <button
16
+ class="save-btn"
17
+ on:click={onSave}
18
+ {disabled}
19
+ title={saveTitle}
20
+ >
21
+ <i class="fas fa-check"></i>
22
+ </button>
23
+ <button
24
+ class="cancel-btn"
25
+ on:click={onCancel}
26
+ disabled={disabled}
27
+ title={cancelTitle}
28
+ >
29
+ <i class="fas fa-times"></i>
30
+ </button>
31
+ </div>
32
+
33
+ <style lang="scss">
34
+ .inline-actions {
35
+ display: flex;
36
+ gap: var(--space-8);
37
+ }
38
+
39
+ .save-btn,
40
+ .cancel-btn {
41
+ padding: var(--space-4) var(--space-8);
42
+ border: none;
43
+ border-radius: var(--radius-md);
44
+ cursor: pointer;
45
+ transition: all 0.2s;
46
+ display: flex;
47
+ align-items: center;
48
+ gap: var(--space-8);
49
+
50
+ &:disabled {
51
+ opacity: 0.5;
52
+ cursor: not-allowed;
53
+ }
54
+ }
55
+
56
+ .save-btn {
57
+ background: rgba(144, 238, 144, 0.2);
58
+ color: #90ee90;
59
+
60
+ &:hover:not(:disabled) {
61
+ background: rgba(144, 238, 144, 0.3);
62
+ }
63
+ }
64
+
65
+ .cancel-btn {
66
+ background: rgba(255, 107, 107, 0.2);
67
+ color: #ff6b6b;
68
+
69
+ &:hover:not(:disabled) {
70
+ background: rgba(255, 107, 107, 0.3);
71
+ }
72
+ }
73
+ </style>
@@ -0,0 +1,308 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher } from 'svelte';
3
+ import Button from './Button.svelte';
4
+
5
+ export let title: string;
6
+ export let description: string;
7
+ export let impact: string = '';
8
+ export let variant: 'info' | 'warning' | 'danger' | 'success' = 'info';
9
+ export let size: 'normal' | 'compact' = 'normal';
10
+ export let icon: string = '';
11
+ export let dismissible: boolean = false;
12
+ export let emphasis: boolean = false;
13
+
14
+ // Action button props
15
+ export let actionText: string = '';
16
+ export let actionIcon: string = '';
17
+ export let onAction: (() => void) | undefined = undefined;
18
+ export let actionInline: boolean = false;
19
+ export let actionHeader: boolean = false; // NEW: Show action button in header row
20
+
21
+ const dispatch = createEventDispatcher();
22
+
23
+ // Default icons based on variant
24
+ const defaultIcons = {
25
+ info: 'fas fa-info-circle',
26
+ warning: 'fas fa-exclamation-triangle',
27
+ danger: 'fas fa-times-circle',
28
+ success: 'fas fa-check-circle'
29
+ };
30
+
31
+ $: displayIcon = icon || defaultIcons[variant];
32
+
33
+ function handleDismiss() {
34
+ dispatch('dismiss');
35
+ }
36
+ </script>
37
+
38
+ <div class="notification" class:info={variant === 'info'} class:warning={variant === 'warning'} class:danger={variant === 'danger'} class:success={variant === 'success'} class:emphasis={emphasis} class:compact={size === 'compact'}>
39
+ <div class="notification-header" class:has-action={actionHeader && onAction}>
40
+ <i class={displayIcon}></i>
41
+ <span class="notification-title">{title}</span>
42
+ {#if actionHeader && onAction}
43
+ <div class="action-button-backdrop">
44
+ <Button variant="outline" icon={actionIcon} on:click={onAction}>
45
+ {actionText}
46
+ </Button>
47
+ </div>
48
+ {/if}
49
+ {#if dismissible}
50
+ <button class="notification-close" on:click={handleDismiss} type="button" aria-label="Dismiss">
51
+ <i class="fas fa-times"></i>
52
+ </button>
53
+ {/if}
54
+ </div>
55
+ {#if description && !actionInline}
56
+ <div class="notification-description">{description}</div>
57
+ {/if}
58
+ {#if impact}
59
+ <div class="notification-impact">{impact}</div>
60
+ {/if}
61
+ <slot />
62
+ {#if onAction && !actionHeader}
63
+ {#if actionInline}
64
+ <div class="notification-actions-inline">
65
+ {#if description}
66
+ <span class="description-text">{description}</span>
67
+ {/if}
68
+ <Button variant="outline" icon={actionIcon} on:click={onAction}>
69
+ {actionText}
70
+ </Button>
71
+ </div>
72
+ {:else}
73
+ <div class="notification-actions">
74
+ <Button variant="outline" icon={actionIcon} on:click={onAction}>
75
+ {actionText}
76
+ </Button>
77
+ </div>
78
+ {/if}
79
+ {/if}
80
+ </div>
81
+
82
+ <style lang="scss">
83
+ .notification {
84
+ display: flex;
85
+ flex-direction: column;
86
+ align-items: flex-start;
87
+ width: 100%;
88
+ gap: 0;
89
+ border-radius: var(--radius-md);
90
+ font-size: var(--font-md);
91
+ border: 1px solid;
92
+ transition: all var(--transition-fast);
93
+ position: relative;
94
+ text-align: left;
95
+ overflow: hidden;
96
+
97
+ &.emphasis {
98
+ border-left-width: 0.375rem;
99
+ }
100
+
101
+ &.compact {
102
+ font-size: var(--font-sm);
103
+
104
+ .notification-header {
105
+ padding: var(--space-6) var(--space-12);
106
+
107
+ i {
108
+ font-size: var(--font-sm);
109
+ }
110
+
111
+ .notification-title {
112
+ font-size: var(--font-md);
113
+ }
114
+ }
115
+
116
+ .notification-description {
117
+ font-size: var(--font-sm);
118
+ padding: var(--space-8) var(--space-12);
119
+ }
120
+
121
+ .notification-impact {
122
+ font-size: var(--font-sm);
123
+ padding: var(--space-8) var(--space-12);
124
+ }
125
+
126
+ .notification-actions-inline {
127
+ padding: var(--space-8) var(--space-12);
128
+
129
+ .description-text {
130
+ font-size: var(--font-sm);
131
+ }
132
+ }
133
+
134
+ .notification-actions {
135
+ padding: var(--space-8) var(--space-12);
136
+ }
137
+ }
138
+
139
+ // Info variant (blue)
140
+ &.info {
141
+ border-color: var(--border-info-darker);
142
+ color: var(--text-primary);
143
+
144
+ .notification-header {
145
+ background: var(--surface-info-low);
146
+
147
+ i {
148
+ color: var(--text-info);
149
+ }
150
+ }
151
+ }
152
+
153
+ // Warning variant (orange)
154
+ &.warning {
155
+ border-color: var(--border-warning);
156
+ color: var(--text-primary);
157
+
158
+ .notification-header {
159
+ background: var(--surface-warning);
160
+
161
+ i {
162
+ color: var(--text-warning);
163
+ }
164
+ }
165
+ }
166
+
167
+ // Danger variant (red)
168
+ &.danger {
169
+ border-color: var(--border-danger);
170
+ color: var(--text-primary);
171
+
172
+ .notification-header {
173
+ background: var(--surface-primary);
174
+
175
+ i {
176
+ color: var(--text-danger);
177
+ }
178
+ }
179
+ }
180
+
181
+ // Success variant (green)
182
+ &.success {
183
+ border-color: var(--border-success);
184
+ color: var(--text-primary);
185
+
186
+ .notification-header {
187
+ background: var(--surface-success);
188
+
189
+ i {
190
+ color: var(--text-success);
191
+ }
192
+ }
193
+ }
194
+ }
195
+
196
+ .notification-header {
197
+ display: flex;
198
+ align-items: center;
199
+ justify-content: flex-start;
200
+ gap: var(--space-8);
201
+ width: 100%;
202
+ padding: .5rem var(--space-16);
203
+ position: relative;
204
+
205
+ // When action button is in header, add spacing
206
+ &.has-action {
207
+ gap: var(--space-12);
208
+ }
209
+
210
+ i {
211
+ font-size: var(--font-md);
212
+ flex-shrink: 0;
213
+ }
214
+
215
+ .notification-title {
216
+ font-weight: var(--font-weight-semibold);
217
+ font-size: var(--font-lg);
218
+ text-align: left;
219
+ flex: 1;
220
+ }
221
+
222
+ .action-button-backdrop {
223
+ flex-shrink: 0;
224
+ background: var(--surface-neutral-lowest);
225
+ border-radius: var(--radius-md);
226
+ }
227
+
228
+ .notification-close {
229
+ position: absolute;
230
+ top: 50%;
231
+ right: 0.5rem;
232
+ transform: translateY(-50%);
233
+ background: none;
234
+ border: none;
235
+ cursor: pointer;
236
+ padding: var(--space-4);
237
+ display: flex;
238
+ align-items: center;
239
+ justify-content: center;
240
+ opacity: 0.7;
241
+ transition: opacity var(--transition-fast);
242
+
243
+ i {
244
+ font-size: var(--font-sm);
245
+ color: inherit;
246
+ }
247
+
248
+ &:hover {
249
+ opacity: 1;
250
+ }
251
+
252
+ &:focus {
253
+ outline: 2px solid currentColor;
254
+ outline-offset: 0.125rem;
255
+ border-radius: var(--radius-sm);
256
+ }
257
+ }
258
+ }
259
+
260
+ .notification-description {
261
+ line-height: 1.4;
262
+ font-size: var(--font-md);
263
+ font-weight: var(--font-weight-light);
264
+ text-align: left;
265
+ padding: .75rem var(--space-16);
266
+ }
267
+
268
+ .notification-impact {
269
+ font-weight: var(--font-weight-bold);
270
+ padding: var(--space-8) var(--space-16);
271
+ padding-bottom: var(--space-12);
272
+ margin-top: 0;
273
+ border-top: 1px solid var(--border-neutral-subtle);
274
+ font-size: var(--font-md);
275
+ text-align: left;
276
+ width: 100%;
277
+ }
278
+
279
+ // Action buttons - inline variant
280
+ .notification-actions-inline {
281
+ display: flex;
282
+ align-items: center;
283
+ gap: var(--space-16);
284
+ padding: var(--space-12) var(--space-16);
285
+
286
+ .description-text {
287
+ flex: 1;
288
+ line-height: 1.4;
289
+ font-size: var(--font-md);
290
+ font-weight: var(--font-weight-light);
291
+ }
292
+
293
+ // Button stays on the right (doesn't shrink or grow)
294
+ :global(button) {
295
+ flex-shrink: 0;
296
+ margin-left: auto;
297
+ }
298
+ }
299
+
300
+ // Action buttons - standard (below description)
301
+ .notification-actions {
302
+ display: flex;
303
+ gap: var(--space-8);
304
+ padding: var(--space-12) var(--space-16);
305
+ padding-top: var(--space-8);
306
+ border-top: 1px solid var(--border-neutral-subtle);
307
+ }
308
+ </style>