@picked/svelte 0.0.45-next.1 → 0.0.45-next.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 (44) hide show
  1. package/dist/plugins/devtools/DevToolsExperience.svelte +61 -44
  2. package/dist/plugins/devtools/components/ExperienceInstanceListItem.svelte +2 -1
  3. package/dist/plugins/devtools/components/ExperienceInstancesTable.svelte +22 -20
  4. package/dist/plugins/devtools/components/Tabs.svelte +20 -7
  5. package/dist/plugins/devtools/experience.js +1 -1
  6. package/dist/plugins/devtools/screens/components/ComponentsListScreen.svelte +18 -18
  7. package/dist/plugins/devtools/screens/events/EventListItem.svelte +28 -42
  8. package/dist/plugins/devtools/screens/events/EventsListScreen.svelte +10 -11
  9. package/dist/plugins/devtools/screens/events/EventsTable.svelte +31 -33
  10. package/dist/plugins/devtools/screens/experiences/ExperienceDetailsScreen.svelte +13 -16
  11. package/dist/plugins/devtools/screens/experiences/ExperienceTreeScreen.svelte +20 -71
  12. package/dist/plugins/devtools/screens/features/FeaturesListScreen.svelte +96 -232
  13. package/dist/plugins/devtools/screens/frameworks/FrameworksListScreen.svelte +14 -16
  14. package/dist/plugins/devtools/screens/history/HistoryEntriesTable.svelte +18 -16
  15. package/dist/plugins/devtools/screens/predicates/PredicatesListScreen.svelte +14 -16
  16. package/dist/plugins/devtools/screens/responses/ResponseTableRow.svelte +25 -63
  17. package/dist/plugins/devtools/screens/responses/ResponsesTable.svelte +43 -64
  18. package/dist/plugins/devtools/ui/actions/Button.svelte +171 -0
  19. package/dist/plugins/devtools/ui/actions/CopyButton.svelte +88 -0
  20. package/dist/plugins/devtools/ui/data/Badge.svelte +62 -0
  21. package/dist/plugins/devtools/ui/data/CodeBlock.svelte +38 -0
  22. package/dist/plugins/devtools/ui/data/DataTable.svelte +134 -0
  23. package/dist/plugins/devtools/ui/data/EmptyState.svelte +26 -0
  24. package/dist/plugins/devtools/ui/data/ExpandableRow.svelte +66 -0
  25. package/dist/plugins/devtools/ui/data/VisualizationContainer.svelte +55 -0
  26. package/dist/plugins/devtools/ui/feedback/Banner.svelte +116 -0
  27. package/dist/plugins/devtools/ui/feedback/Spinner.svelte +79 -0
  28. package/dist/plugins/devtools/ui/forms/Checkbox.svelte +139 -0
  29. package/dist/plugins/devtools/ui/forms/RadioGroup.svelte +218 -0
  30. package/dist/plugins/devtools/ui/forms/Select.svelte +137 -0
  31. package/dist/plugins/devtools/ui/forms/Switch.svelte +158 -0
  32. package/dist/plugins/devtools/ui/forms/TextField.svelte +125 -0
  33. package/dist/plugins/devtools/ui/index.d.ts +22 -0
  34. package/dist/plugins/devtools/ui/index.js +1 -0
  35. package/dist/plugins/devtools/ui/layout/Card.svelte +55 -0
  36. package/dist/plugins/devtools/ui/layout/Divider.svelte +34 -0
  37. package/dist/plugins/devtools/ui/layout/Spacer.svelte +11 -0
  38. package/dist/plugins/devtools/ui/layout/Stack.svelte +129 -0
  39. package/dist/plugins/devtools/ui/overlays/Tooltip.svelte +90 -0
  40. package/dist/plugins/devtools/ui/tokens.css +144 -0
  41. package/dist/plugins/devtools/ui/tokens.css.js +1 -0
  42. package/dist/plugins/devtools/ui/typography/Heading.svelte +55 -0
  43. package/dist/plugins/devtools/ui/typography/Text.svelte +93 -0
  44. package/package.json +5 -2
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ code: string
4
+ inline?: boolean
5
+ }
6
+
7
+ let { code, inline = false }: Props = $props()
8
+ </script>
9
+
10
+ {#if inline}
11
+ <code class="code-inline">{code}</code>
12
+ {:else}
13
+ <pre class="code-block"><code>{code}</code></pre>
14
+ {/if}
15
+
16
+ <style>
17
+ .code-inline {
18
+ font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
19
+ font-size: var(--text-xs);
20
+ background-color: var(--color-gray-100);
21
+ border: 1px solid var(--color-gray-200);
22
+ border-radius: var(--radius-md);
23
+ padding: var(--space-0-5) var(--space-1);
24
+ }
25
+
26
+ .code-block {
27
+ font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
28
+ font-size: var(--text-xs);
29
+ background-color: var(--color-gray-50);
30
+ border: 1px solid var(--color-gray-200);
31
+ border-radius: var(--radius-md);
32
+ padding: var(--space-3);
33
+ margin: 0;
34
+ overflow-x: auto;
35
+ white-space: pre-wrap;
36
+ word-break: break-all;
37
+ }
38
+ </style>
@@ -0,0 +1,134 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
3
+
4
+ interface Column {
5
+ key: string
6
+ header: string
7
+ sortable?: boolean
8
+ }
9
+
10
+ interface Props {
11
+ columns: Column[]
12
+ rows: unknown[]
13
+ row: Snippet<[unknown, number]>
14
+ empty?: Snippet
15
+ sortKey?: string | null
16
+ sortDirection?: 'asc' | 'desc'
17
+ onSort?: (key: string) => void
18
+ }
19
+
20
+ let {
21
+ columns,
22
+ rows,
23
+ row,
24
+ empty,
25
+ sortKey = null,
26
+ sortDirection = 'asc',
27
+ onSort,
28
+ }: Props = $props()
29
+
30
+ function handleHeaderClick(column: Column): void {
31
+ if (column.sortable && onSort) {
32
+ onSort(column.key)
33
+ }
34
+ }
35
+
36
+ function handleHeaderKeydown(event: KeyboardEvent, column: Column): void {
37
+ if ((event.key === 'Enter' || event.key === ' ') && column.sortable && onSort) {
38
+ event.preventDefault()
39
+ onSort(column.key)
40
+ }
41
+ }
42
+ </script>
43
+
44
+ <table class="data-table">
45
+ <thead>
46
+ <tr>
47
+ {#each columns as column}
48
+ <th
49
+ class:sortable={column.sortable}
50
+ aria-sort={column.sortable && sortKey === column.key
51
+ ? sortDirection === 'asc' ? 'ascending' : 'descending'
52
+ : undefined}
53
+ onclick={() => handleHeaderClick(column)}
54
+ onkeydown={(e: KeyboardEvent) => handleHeaderKeydown(e, column)}
55
+ tabindex={column.sortable ? 0 : undefined}
56
+ role={column.sortable ? 'columnheader button' : 'columnheader'}
57
+ >
58
+ {column.header}
59
+ {#if column.sortable && sortKey === column.key}
60
+ <span class="sort-indicator">{sortDirection === 'asc' ? '↑' : '↓'}</span>
61
+ {/if}
62
+ </th>
63
+ {/each}
64
+ </tr>
65
+ </thead>
66
+ <tbody>
67
+ {#if rows.length === 0 && empty}
68
+ <tr>
69
+ <td colspan={columns.length} class="empty-cell">
70
+ {@render empty()}
71
+ </td>
72
+ </tr>
73
+ {:else}
74
+ {#each rows as item, index}
75
+ {@render row(item, index)}
76
+ {/each}
77
+ {/if}
78
+ </tbody>
79
+ </table>
80
+
81
+ <style>
82
+ .data-table {
83
+ width: 100%;
84
+ border-collapse: collapse;
85
+ }
86
+
87
+ th {
88
+ padding: var(--space-2);
89
+ text-align: left;
90
+ font-weight: var(--font-medium);
91
+ font-size: var(--text-sm);
92
+ color: var(--color-gray-700);
93
+ background-color: var(--color-gray-50);
94
+ border-bottom: 1px solid var(--color-gray-200);
95
+ }
96
+
97
+ th.sortable {
98
+ cursor: pointer;
99
+ user-select: none;
100
+ }
101
+
102
+ th.sortable:hover {
103
+ background-color: var(--color-gray-100);
104
+ }
105
+
106
+ th.sortable:focus-visible {
107
+ outline: var(--ring-width) solid var(--ring-color);
108
+ outline-offset: calc(-1 * var(--ring-width));
109
+ }
110
+
111
+ .sort-indicator {
112
+ margin-left: var(--space-1);
113
+ }
114
+
115
+ .empty-cell {
116
+ padding: 0;
117
+ }
118
+
119
+ :global(tbody td) {
120
+ padding: var(--space-2);
121
+ text-align: left;
122
+ font-size: var(--text-sm);
123
+ color: var(--color-gray-900);
124
+ border-bottom: 1px solid var(--color-gray-200);
125
+ }
126
+
127
+ :global(tbody tr:hover) {
128
+ background-color: var(--color-gray-50);
129
+ }
130
+
131
+ :global(tbody tr.selected) {
132
+ background-color: color-mix(in srgb, var(--color-blue-500) 8%, var(--color-white));
133
+ }
134
+ </style>
@@ -0,0 +1,26 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ message: string
4
+ }
5
+
6
+ let { message }: Props = $props()
7
+ </script>
8
+
9
+ <div class="empty-state">
10
+ <p class="message">{message}</p>
11
+ </div>
12
+
13
+ <style>
14
+ .empty-state {
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ padding: var(--space-8);
19
+ }
20
+
21
+ .message {
22
+ color: var(--color-gray-500);
23
+ font-size: var(--text-sm);
24
+ margin: 0;
25
+ }
26
+ </style>
@@ -0,0 +1,66 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
3
+
4
+ interface Props {
5
+ expanded?: boolean
6
+ onToggle?: () => void
7
+ summary: Snippet
8
+ details: Snippet
9
+ colspan?: number
10
+ }
11
+
12
+ let {
13
+ expanded = false,
14
+ onToggle,
15
+ summary,
16
+ details,
17
+ colspan = 1,
18
+ }: Props = $props()
19
+
20
+ function handleKeydown(event: KeyboardEvent): void {
21
+ if (event.key === 'Enter' || event.key === ' ') {
22
+ event.preventDefault()
23
+ onToggle?.()
24
+ }
25
+ }
26
+ </script>
27
+
28
+ <tr
29
+ class="expandable-row"
30
+ class:expanded
31
+ role="button"
32
+ tabindex="0"
33
+ aria-expanded={expanded}
34
+ onclick={() => onToggle?.()}
35
+ onkeydown={handleKeydown}
36
+ >
37
+ {@render summary()}
38
+ </tr>
39
+ {#if expanded}
40
+ <tr class="details-row">
41
+ <td {colspan} class="details-cell">
42
+ {@render details()}
43
+ </td>
44
+ </tr>
45
+ {/if}
46
+
47
+ <style>
48
+ .expandable-row {
49
+ cursor: pointer;
50
+ }
51
+
52
+ .expandable-row:hover {
53
+ background-color: var(--color-gray-50);
54
+ }
55
+
56
+ .expandable-row:focus-visible {
57
+ outline: var(--ring-width) solid var(--ring-color);
58
+ outline-offset: calc(-1 * var(--ring-width));
59
+ }
60
+
61
+ .details-cell {
62
+ background-color: var(--color-gray-50);
63
+ border-left: 3px solid var(--color-blue-500);
64
+ padding: var(--space-3);
65
+ }
66
+ </style>
@@ -0,0 +1,55 @@
1
+ <!--
2
+ Container for interactive visualizations (e.g., D3 tree graphs).
3
+ Provides a bordered frame with an optional controls overlay.
4
+ -->
5
+ <script lang="ts">
6
+ import type { Snippet } from 'svelte'
7
+
8
+ interface Props {
9
+ children: Snippet
10
+ controls?: Snippet
11
+ }
12
+
13
+ let { children, controls }: Props = $props()
14
+ </script>
15
+
16
+ <div class="visualization">
17
+ {#if controls}
18
+ <div class="controls">
19
+ {@render controls()}
20
+ </div>
21
+ {/if}
22
+ <div class="content">
23
+ {@render children()}
24
+ </div>
25
+ </div>
26
+
27
+ <style>
28
+ .visualization {
29
+ position: relative;
30
+ height: 100%;
31
+ width: 100%;
32
+ border: 1px solid var(--color-gray-300);
33
+ overflow: hidden;
34
+ }
35
+
36
+ .controls {
37
+ position: absolute;
38
+ right: var(--space-4);
39
+ top: var(--space-4);
40
+ z-index: 10;
41
+ display: flex;
42
+ gap: var(--space-2);
43
+ }
44
+
45
+ .content {
46
+ height: 100%;
47
+ width: 100%;
48
+ }
49
+
50
+ .content :global(svg) {
51
+ height: 100%;
52
+ width: 100%;
53
+ background-color: var(--color-white);
54
+ }
55
+ </style>
@@ -0,0 +1,116 @@
1
+ <!--
2
+ @paired-component apps/dashboard/src/shared/ui/feedback/banner.tsx
3
+ @design-parity Props, variants, sizes, and visual output must stay in sync
4
+ with the Dashboard React counterpart. When modifying this component, replicate
5
+ the change in the paired React component to maintain visual and behavioral parity.
6
+ -->
7
+ <script lang="ts">
8
+ import type { Snippet } from 'svelte'
9
+
10
+ interface Props {
11
+ children: Snippet
12
+ status?: 'info' | 'success' | 'warning' | 'error'
13
+ title?: string
14
+ onDismiss?: () => void
15
+ }
16
+
17
+ let { children, status = 'info', title, onDismiss }: Props = $props()
18
+
19
+ const bannerRole = $derived(
20
+ status === 'error' || status === 'warning' ? 'alert' : 'status',
21
+ )
22
+ </script>
23
+
24
+ <div class="banner status-{status}" role={bannerRole}>
25
+ <div class="banner-content">
26
+ {#if title}
27
+ <p class="banner-title">{title}</p>
28
+ {/if}
29
+ <div class="banner-body">
30
+ {@render children()}
31
+ </div>
32
+ </div>
33
+ {#if onDismiss}
34
+ <button
35
+ class="dismiss-button"
36
+ onclick={onDismiss}
37
+ aria-label="Dismiss"
38
+ >
39
+ <svg class="dismiss-icon" viewBox="0 0 20 20" fill="currentColor">
40
+ <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
41
+ </svg>
42
+ </button>
43
+ {/if}
44
+ </div>
45
+
46
+ <style>
47
+ .banner {
48
+ display: flex;
49
+ align-items: flex-start;
50
+ gap: var(--space-3);
51
+ border-radius: var(--radius-md);
52
+ border: 1px solid;
53
+ padding: var(--space-4);
54
+ background-color: var(--color-white);
55
+ }
56
+
57
+ .status-info {
58
+ border-color: #bfdbfe;
59
+ color: var(--color-blue-800, #1e40af);
60
+ }
61
+ .status-success {
62
+ border-color: #bbf7d0;
63
+ color: var(--color-green-800);
64
+ }
65
+ .status-warning {
66
+ border-color: #fef08a;
67
+ color: var(--color-yellow-800);
68
+ }
69
+ .status-error {
70
+ border-color: #fecaca;
71
+ color: var(--color-red-700);
72
+ }
73
+
74
+ .banner-content {
75
+ flex: 1;
76
+ display: flex;
77
+ flex-direction: column;
78
+ gap: var(--space-1);
79
+ }
80
+
81
+ .banner-title {
82
+ font-weight: var(--font-semibold);
83
+ font-size: var(--text-sm);
84
+ margin: 0;
85
+ }
86
+
87
+ .banner-body {
88
+ font-size: var(--text-sm);
89
+ }
90
+
91
+ .dismiss-button {
92
+ margin-left: var(--space-4);
93
+ border-radius: var(--radius-sm);
94
+ background: none;
95
+ border: none;
96
+ color: currentColor;
97
+ opacity: 0.7;
98
+ cursor: pointer;
99
+ padding: 0;
100
+ transition: opacity 0.15s ease;
101
+ }
102
+
103
+ .dismiss-button:hover {
104
+ opacity: 1;
105
+ }
106
+
107
+ .dismiss-button:focus-visible {
108
+ outline: var(--ring-width) solid currentColor;
109
+ outline-offset: var(--ring-offset);
110
+ }
111
+
112
+ .dismiss-icon {
113
+ width: 1.25rem;
114
+ height: 1.25rem;
115
+ }
116
+ </style>
@@ -0,0 +1,79 @@
1
+ <!--
2
+ @paired-component apps/dashboard/src/shared/ui/feedback/spinner.tsx
3
+ @design-parity Props, variants, sizes, and visual output must stay in sync
4
+ with the Dashboard React counterpart. When modifying this component, replicate
5
+ the change in the paired React component to maintain visual and behavioral parity.
6
+ -->
7
+ <script lang="ts">
8
+ interface Props {
9
+ size?: 'small' | 'medium' | 'large'
10
+ label?: string
11
+ color?: 'primary' | 'current'
12
+ }
13
+
14
+ let { size = 'medium', label = 'Loading', color = 'primary' }: Props = $props()
15
+
16
+ const dimensions = $derived(
17
+ size === 'small' ? 16 : size === 'large' ? 32 : 24,
18
+ )
19
+ const strokeWidth = $derived(
20
+ size === 'small' ? 2 : size === 'large' ? 4 : 3,
21
+ )
22
+ const r = $derived((dimensions - strokeWidth) / 2)
23
+ const circumference = $derived(2 * Math.PI * r)
24
+ </script>
25
+
26
+ <svg
27
+ class="spinner color-{color}"
28
+ width={dimensions}
29
+ height={dimensions}
30
+ viewBox="0 0 {dimensions} {dimensions}"
31
+ role="progressbar"
32
+ aria-label={label}
33
+ >
34
+ <circle
35
+ class="track"
36
+ cx={dimensions / 2}
37
+ cy={dimensions / 2}
38
+ r={r}
39
+ fill="none"
40
+ stroke="currentColor"
41
+ stroke-width={strokeWidth}
42
+ />
43
+ <circle
44
+ class="arc"
45
+ cx={dimensions / 2}
46
+ cy={dimensions / 2}
47
+ r={r}
48
+ fill="none"
49
+ stroke="currentColor"
50
+ stroke-width={strokeWidth}
51
+ stroke-dasharray="{circumference * 0.25} {circumference * 0.75}"
52
+ transform="rotate(-90 {dimensions / 2} {dimensions / 2})"
53
+ >
54
+ <animateTransform
55
+ attributeName="transform"
56
+ type="rotate"
57
+ from="0 {dimensions / 2} {dimensions / 2}"
58
+ to="360 {dimensions / 2} {dimensions / 2}"
59
+ dur="1s"
60
+ repeatCount="indefinite"
61
+ />
62
+ </circle>
63
+ </svg>
64
+
65
+ <style>
66
+ .color-primary {
67
+ color: var(--color-blue-600);
68
+ }
69
+ .color-current {
70
+ color: currentColor;
71
+ }
72
+
73
+ .track {
74
+ opacity: 0.25;
75
+ }
76
+ .arc {
77
+ opacity: 0.75;
78
+ }
79
+ </style>
@@ -0,0 +1,139 @@
1
+ <!--
2
+ @paired-component apps/dashboard/src/shared/ui/forms/checkbox.tsx
3
+ @design-parity Props, variants, sizes, and visual output must stay in sync
4
+ with the Dashboard React counterpart. When modifying this component, replicate
5
+ the change in the paired React component to maintain visual and behavioral parity.
6
+ -->
7
+ <script lang="ts">
8
+ interface Props {
9
+ label: string
10
+ name: string
11
+ checked?: boolean
12
+ onchange?: (checked: boolean) => void
13
+ helpText?: string
14
+ disabled?: boolean
15
+ }
16
+
17
+ let {
18
+ label,
19
+ name,
20
+ checked = false,
21
+ onchange,
22
+ helpText,
23
+ disabled = false,
24
+ }: Props = $props()
25
+
26
+ function handleChange(event: Event): void {
27
+ if (event.target instanceof HTMLInputElement) {
28
+ onchange?.(event.target.checked)
29
+ }
30
+ }
31
+ </script>
32
+
33
+ <div class="checkbox-field">
34
+ <label class="checkbox-label" class:is-disabled={disabled}>
35
+ <span class="checkbox-wrapper">
36
+ <input
37
+ type="checkbox"
38
+ class="checkbox-input"
39
+ {name}
40
+ {checked}
41
+ {disabled}
42
+ onchange={handleChange}
43
+ />
44
+ <span class="checkbox-box" class:checked aria-hidden="true">
45
+ {#if checked}
46
+ <svg class="checkmark" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2">
47
+ <polyline points="2,6 5,9 10,3" />
48
+ </svg>
49
+ {/if}
50
+ </span>
51
+ </span>
52
+ <span class="label-text">{label}</span>
53
+ </label>
54
+ {#if helpText}
55
+ <p class="help-text">{helpText}</p>
56
+ {/if}
57
+ </div>
58
+
59
+ <style>
60
+ .checkbox-field {
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: var(--space-1);
64
+ }
65
+
66
+ .checkbox-label {
67
+ display: flex;
68
+ cursor: pointer;
69
+ align-items: center;
70
+ gap: var(--space-2);
71
+ }
72
+
73
+ .checkbox-label.is-disabled {
74
+ cursor: not-allowed;
75
+ opacity: 0.5;
76
+ }
77
+
78
+ .checkbox-wrapper {
79
+ position: relative;
80
+ width: 1rem;
81
+ height: 1rem;
82
+ flex-shrink: 0;
83
+ }
84
+
85
+ .checkbox-input {
86
+ position: absolute;
87
+ inset: 0;
88
+ z-index: 10;
89
+ cursor: pointer;
90
+ opacity: 0;
91
+ margin: 0;
92
+ }
93
+
94
+ .checkbox-input:disabled {
95
+ cursor: not-allowed;
96
+ }
97
+
98
+ .checkbox-box {
99
+ pointer-events: none;
100
+ position: absolute;
101
+ inset: 0;
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ border-radius: var(--radius-sm);
106
+ border: 1px solid var(--color-gray-300);
107
+ background-color: var(--color-white);
108
+ transition: background-color 0.15s ease, border-color 0.15s ease;
109
+ }
110
+
111
+ .checkbox-box.checked {
112
+ border-color: var(--color-blue-600);
113
+ background-color: var(--color-blue-600);
114
+ }
115
+
116
+ .checkbox-input:focus-visible + .checkbox-box {
117
+ outline: var(--ring-width) solid var(--ring-color);
118
+ outline-offset: var(--ring-offset);
119
+ }
120
+
121
+ .checkmark {
122
+ width: 0.75rem;
123
+ height: 0.75rem;
124
+ color: var(--color-white);
125
+ }
126
+
127
+ .label-text {
128
+ font-size: var(--text-sm);
129
+ font-weight: var(--font-medium);
130
+ color: var(--color-gray-900);
131
+ }
132
+
133
+ .help-text {
134
+ margin: 0;
135
+ margin-left: 1.5rem;
136
+ font-size: var(--text-sm);
137
+ color: var(--color-gray-500);
138
+ }
139
+ </style>