@picked/svelte 0.0.1-dev.1788925875333 → 0.0.1-next.1

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 (132) hide show
  1. package/dist/component.d.ts +5 -5
  2. package/dist/component.js +1 -1
  3. package/dist/context.js +1 -1
  4. package/dist/form/index.d.ts +15 -3
  5. package/dist/form/index.js +1 -1
  6. package/dist/hooks/client.d.ts +1 -1
  7. package/dist/hooks/client.js +1 -1
  8. package/dist/hooks/field.d.ts +5 -16
  9. package/dist/hooks/field.js +1 -1
  10. package/dist/hooks/index.d.ts +1 -9
  11. package/dist/hooks/index.js +1 -1
  12. package/dist/hooks/step.d.ts +15 -93
  13. package/dist/hooks/step.js +1 -1
  14. package/dist/hooks/storage.d.ts +2 -2
  15. package/dist/hooks/storage.js +1 -1
  16. package/dist/hooks/stores.d.ts +1 -1
  17. package/dist/hooks/stores.js +1 -1
  18. package/dist/index.d.ts +1 -8
  19. package/dist/index.js +1 -1
  20. package/dist/plugins/devtools/DevToolsExperience.svelte +53 -355
  21. package/dist/plugins/devtools/PickedLogo.svelte +58 -0
  22. package/dist/plugins/devtools/components/ExperienceInstanceListItem.svelte +4 -17
  23. package/dist/plugins/devtools/components/ExperienceInstancesTable.svelte +19 -26
  24. package/dist/plugins/devtools/components/Tabs.svelte +12 -69
  25. package/dist/plugins/devtools/experience.d.ts +1 -0
  26. package/dist/plugins/devtools/experience.js +1 -0
  27. package/dist/plugins/devtools/index.d.ts +0 -2
  28. package/dist/plugins/devtools/index.js +1 -1
  29. package/dist/plugins/devtools/plugin.d.ts +5 -37
  30. package/dist/plugins/devtools/plugin.js +1 -1
  31. package/dist/plugins/devtools/screens/components/ComponentsListScreen.svelte +14 -18
  32. package/dist/plugins/devtools/screens/experience-instances/ExperienceInstancesListScreen.svelte +3 -1
  33. package/dist/plugins/devtools/screens/experiences/ExperienceDetailsScreen.svelte +33 -31
  34. package/dist/plugins/devtools/screens/experiences/ExperienceExperienceInstancesListScreen.svelte +3 -1
  35. package/dist/plugins/devtools/screens/experiences/ExperienceTreeScreen.svelte +103 -293
  36. package/dist/plugins/devtools/screens/experiences/ExperiencesListScreen.svelte +1 -2
  37. package/dist/plugins/devtools/screens/frameworks/FrameworksListScreen.svelte +13 -15
  38. package/dist/plugins/devtools/screens/history/HistoryEntriesTable.svelte +16 -22
  39. package/dist/plugins/devtools/screens/history/HistoryEntryListItem.svelte +1 -7
  40. package/dist/plugins/devtools/screens/predicates/PredicatesListScreen.svelte +13 -15
  41. package/dist/plugins/devtools/screens/project/ProjectScreen.svelte +1 -46
  42. package/dist/plugins/framework/index.js +1 -1
  43. package/dist/plugins/framework/plugin.d.ts +4 -4
  44. package/dist/plugins/framework/plugin.js +1 -1
  45. package/dist/render/browser.d.ts +2 -35
  46. package/dist/render/browser.js +1 -1
  47. package/dist/render/server.d.ts +8 -22
  48. package/dist/render/server.js +1 -1
  49. package/dist/router/Step.svelte +4 -6
  50. package/dist/router/StepRouter.svelte +33 -14
  51. package/dist/router/context.d.ts +3 -3
  52. package/dist/router/context.js +1 -1
  53. package/dist/router/index.js +1 -1
  54. package/dist/server/index.d.ts +2 -2
  55. package/dist/server/index.js +1 -1
  56. package/dist/utils/array.js +1 -1
  57. package/dist/vite-env.d.js +1 -0
  58. package/package.json +33 -106
  59. package/dist/.tsbuildinfo +0 -1
  60. package/dist/_virtual/_vite/preload-helper.js +0 -1
  61. package/dist/components/LazyImage.svelte +0 -192
  62. package/dist/components/index.d.ts +0 -1
  63. package/dist/components/index.js +0 -1
  64. package/dist/experience/ExperienceHost.svelte +0 -112
  65. package/dist/experience/ExperienceSlot.svelte +0 -154
  66. package/dist/experience/HtmlRender.svelte +0 -52
  67. package/dist/experience/set-picked-context.d.ts +0 -29
  68. package/dist/experience/set-picked-context.js +0 -1
  69. package/dist/form/__tests__/CreateFormHarness.svelte +0 -30
  70. package/dist/form/create-form.js +0 -1
  71. package/dist/form/create-form.svelte.d.ts +0 -40
  72. package/dist/form/create-form.svelte.js +0 -1
  73. package/dist/form/get-form.d.ts +0 -30
  74. package/dist/form/get-form.js +0 -1
  75. package/dist/hooks/action.d.ts +0 -40
  76. package/dist/hooks/action.js +0 -1
  77. package/dist/hooks/content.d.ts +0 -18
  78. package/dist/hooks/content.js +0 -1
  79. package/dist/hooks/create-query/index.d.ts +0 -145
  80. package/dist/hooks/create-query/index.js +0 -1
  81. package/dist/hooks/events.d.ts +0 -2
  82. package/dist/hooks/events.js +0 -1
  83. package/dist/hooks/feature.d.ts +0 -47
  84. package/dist/hooks/feature.js +0 -1
  85. package/dist/hooks/predicate.d.ts +0 -3
  86. package/dist/hooks/predicate.js +0 -1
  87. package/dist/hooks/reference.d.ts +0 -61
  88. package/dist/hooks/reference.js +0 -1
  89. package/dist/plugins/devtools/PickedIcon.svelte +0 -19
  90. package/dist/plugins/devtools/components/AdaptedToolHost.svelte +0 -103
  91. package/dist/plugins/devtools/customTools.d.ts +0 -27
  92. package/dist/plugins/devtools/customTools.js +0 -1
  93. package/dist/plugins/devtools/screens/config/ConfigScreen.svelte +0 -160
  94. package/dist/plugins/devtools/screens/content/ContentListScreen.svelte +0 -89
  95. package/dist/plugins/devtools/screens/custom-tools/CustomToolsScreen.svelte +0 -29
  96. package/dist/plugins/devtools/screens/events/EventListItem.svelte +0 -216
  97. package/dist/plugins/devtools/screens/events/EventsListScreen.svelte +0 -18
  98. package/dist/plugins/devtools/screens/events/EventsTable.svelte +0 -76
  99. package/dist/plugins/devtools/screens/features/FeaturesListScreen.svelte +0 -239
  100. package/dist/plugins/devtools/screens/fields/FieldTableRow.svelte +0 -276
  101. package/dist/plugins/devtools/screens/fields/FieldsListScreen.svelte +0 -12
  102. package/dist/plugins/devtools/screens/fields/FieldsTable.svelte +0 -78
  103. package/dist/plugins/devtools/screens/identity/IdentityScreen.svelte +0 -66
  104. package/dist/plugins/devtools/screens/responses/ResponseTableRow.svelte +0 -280
  105. package/dist/plugins/devtools/screens/responses/ResponsesListScreen.svelte +0 -12
  106. package/dist/plugins/devtools/screens/responses/ResponsesTable.svelte +0 -88
  107. package/dist/plugins/devtools/ui/actions/Button.svelte +0 -175
  108. package/dist/plugins/devtools/ui/actions/CopyButton.svelte +0 -88
  109. package/dist/plugins/devtools/ui/data/Badge.svelte +0 -62
  110. package/dist/plugins/devtools/ui/data/CodeBlock.svelte +0 -38
  111. package/dist/plugins/devtools/ui/data/DataTable.svelte +0 -144
  112. package/dist/plugins/devtools/ui/data/EmptyState.svelte +0 -26
  113. package/dist/plugins/devtools/ui/data/ExpandableRow.svelte +0 -66
  114. package/dist/plugins/devtools/ui/data/VisualizationContainer.svelte +0 -55
  115. package/dist/plugins/devtools/ui/feedback/Banner.svelte +0 -116
  116. package/dist/plugins/devtools/ui/feedback/Spinner.svelte +0 -79
  117. package/dist/plugins/devtools/ui/forms/Checkbox.svelte +0 -139
  118. package/dist/plugins/devtools/ui/forms/RadioGroup.svelte +0 -218
  119. package/dist/plugins/devtools/ui/forms/Select.svelte +0 -137
  120. package/dist/plugins/devtools/ui/forms/Switch.svelte +0 -158
  121. package/dist/plugins/devtools/ui/forms/TextField.svelte +0 -125
  122. package/dist/plugins/devtools/ui/index.d.ts +0 -22
  123. package/dist/plugins/devtools/ui/index.js +0 -1
  124. package/dist/plugins/devtools/ui/layout/Card.svelte +0 -55
  125. package/dist/plugins/devtools/ui/layout/Divider.svelte +0 -34
  126. package/dist/plugins/devtools/ui/layout/Spacer.svelte +0 -11
  127. package/dist/plugins/devtools/ui/layout/Stack.svelte +0 -129
  128. package/dist/plugins/devtools/ui/overlays/Tooltip.svelte +0 -90
  129. package/dist/plugins/devtools/ui/tokens.css +0 -144
  130. package/dist/plugins/devtools/ui/typography/Heading.svelte +0 -55
  131. package/dist/plugins/devtools/ui/typography/Text.svelte +0 -93
  132. package/dist/utils/ErrorBoundary.svelte +0 -27
@@ -1,61 +0,0 @@
1
- /**
2
- * @file Svelte lookup helpers for `reference` field values. A `reference` field
3
- * delivers a pointer at another Content record; the record itself is registered
4
- * separately, so resolving a pointer is a lookup against the content registry.
5
- */
6
- import type { Store } from 'effector';
7
- import { type ReferencedContent } from '@picked/client';
8
- /**
9
- * Resolves a single `reference` field value to the Content record it points at.
10
- *
11
- * Call it during component initialisation, like every `get*` helper — it reads
12
- * Svelte context. Pass a *store* of the field rather than a snapshot of it:
13
- * content loads asynchronously, so the blob is still `null` at initialisation
14
- * and a snapshot would pin the lookup to "unset".
15
- *
16
- * When the workspace schema has been generated, the record narrows to the Content Model the
17
- * field targets; otherwise it stays the untyped `Content`.
18
- *
19
- * @template TValue
20
- * @param {TValue} value - The raw `reference` value, or an Effector store carrying one. A
21
- * store keeps the lookup live when the field arrives after this call.
22
- * @returns {Store<ReferencedContent<TValue> | null>} The referenced record, or `null` when the field is unset or its target is not registered.
23
- * @example
24
- * ```svelte
25
- * <script>
26
- * import { getStepContent, getReference } from '@picked/svelte/hooks'
27
- * const content = getStepContent()
28
- * const author = getReference(content.map((c) => c?.author ?? null, { skipVoid: false }))
29
- * </script>
30
- * <span>{$author?.data.name ?? ''}</span>
31
- * ```
32
- */
33
- export declare function getReference<TValue>(value: TValue): Store<ReferencedContent<TValue> | null>;
34
- /**
35
- * Resolves a repeatable `reference` field to the Content records it points at,
36
- * in field order. A single (non-repeatable) value resolves to a one-element list.
37
- *
38
- * The list is dense: a pointer whose target did not resolve is skipped rather
39
- * than held as a hole, so `{#each}` needs no null check per item.
40
- *
41
- * Call it during component initialisation and pass a store of the field, for the
42
- * same reasons as {@link getReference}.
43
- *
44
- * When the workspace schema has been generated, each record narrows to the Content Model the
45
- * field targets; otherwise they stay the untyped `Content`.
46
- *
47
- * @template TValue
48
- * @param {TValue} value - The raw `reference` value, or an Effector store carrying one. A
49
- * store keeps the lookup live when the field arrives after this call.
50
- * @returns {Store<ReferencedContent<TValue>[]>} The referenced records that resolved.
51
- * @example
52
- * ```svelte
53
- * <script>
54
- * import { getStepContent, getReferences } from '@picked/svelte/hooks'
55
- * const content = getStepContent()
56
- * const authors = getReferences(content.map((c) => c?.authors ?? null, { skipVoid: false }))
57
- * </script>
58
- * {#each $authors as author (author.id)}<li>{author.data.name}</li>{/each}
59
- * ```
60
- */
61
- export declare function getReferences<TValue>(value: TValue): Store<ReferencedContent<TValue>[]>;
@@ -1 +0,0 @@
1
- import{getPicked as e}from"./client.js";import{deriveReference as t,deriveReferences as n}from"@picked/client";function r(n){return t(e().contents,n)}function i(t){return n(e().contents,t)}export{r as getReference,i as getReferences};
@@ -1,19 +0,0 @@
1
- <!-- PickedIcon.svelte -->
2
- <script lang="ts">
3
- export let width = 48
4
- export let height = 48
5
- </script>
6
-
7
- <svg {width} {height} viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
8
- <g opacity="0.5">
9
- <ellipse opacity="0.8" cx="32.5807" cy="7.38424" rx="6.29832" ry="6.29832" fill="#01AD7A"/>
10
- <circle opacity="0.6" cx="31.4947" cy="8.47015" r="6.29832" fill="#01AD7A"/>
11
- <ellipse opacity="0.4" cx="30.4088" cy="9.55607" rx="6.29832" ry="6.29832" fill="#01AD7A"/>
12
- <ellipse opacity="0.2" cx="29.3229" cy="10.642" rx="6.29832" ry="6.29832" fill="#01AD7A"/>
13
- <circle opacity="0.1" cx="28.237" cy="11.7279" r="6.29832" fill="#01AD7A"/>
14
- </g>
15
- <ellipse cx="33.6664" cy="6.29832" rx="6.29832" ry="6.29832" fill="#00CD90"/>
16
- <path fill-rule="evenodd" clip-rule="evenodd" d="M12.5997 16.1802C14.5788 16.1802 16.1832 14.5758 16.1832 12.5967C16.1832 10.6175 14.5788 9.01315 12.5997 9.01315C10.6206 9.01315 9.01617 10.6175 9.01617 12.5967C9.01617 14.5758 10.6206 16.1802 12.5997 16.1802ZM12.5997 18.895C16.0782 18.895 18.898 16.0751 18.898 12.5967C18.898 9.11821 16.0782 6.29836 12.5997 6.29836C9.12123 6.29836 6.30138 9.11821 6.30138 12.5967C6.30138 16.0751 9.12123 18.895 12.5997 18.895Z" fill="#1549FF"/>
17
- <path fill-rule="evenodd" clip-rule="evenodd" d="M12.5997 30.9486C14.5788 30.9486 16.1832 29.3442 16.1832 27.3651C16.1832 25.386 14.5788 23.7816 12.5997 23.7816C10.6206 23.7816 9.01617 25.386 9.01617 27.3651C9.01617 29.3442 10.6206 30.9486 12.5997 30.9486ZM12.5997 33.6634C16.0782 33.6634 18.898 30.8436 18.898 27.3651C18.898 23.8866 16.0782 21.0668 12.5997 21.0668C9.12123 21.0668 6.30138 23.8866 6.30138 27.3651C6.30138 30.8436 9.12123 33.6634 12.5997 33.6634Z" fill="#1549FF"/>
18
- <path fill-rule="evenodd" clip-rule="evenodd" d="M27.3683 30.9486C29.3474 30.9486 30.9518 29.3442 30.9518 27.3651C30.9518 25.386 29.3474 23.7816 27.3683 23.7816C25.3891 23.7816 23.7847 25.386 23.7847 27.3651C23.7847 29.3442 25.3891 30.9486 27.3683 30.9486ZM27.3683 33.6634C30.8467 33.6634 33.6666 30.8436 33.6666 27.3651C33.6666 23.8866 30.8467 21.0668 27.3683 21.0668C23.8898 21.0668 21.0699 23.8866 21.0699 27.3651C21.0699 30.8436 23.8898 33.6634 27.3683 33.6634Z" fill="#1549FF"/>
19
- </svg>
@@ -1,103 +0,0 @@
1
- <script lang="ts">
2
- /** @file Renders a custom devtools tool by delegating to its framework's registered renderer. */
3
- import { onDestroy } from 'svelte'
4
- import type { Framework } from '@picked/client'
5
- import { getExperience, getPicked } from '../../../hooks'
6
- import type { CustomTool } from '../customTools'
7
- import { Banner } from '../ui'
8
-
9
- export let tool: CustomTool
10
-
11
- const client = getPicked()
12
- const experience = getExperience()
13
- const frameworkStore = client.frameworks.getByName(tool.component.frameworkName)
14
-
15
- let host: HTMLDivElement | undefined
16
- let rendered = false
17
- let renderFailed = false
18
- let destroyed = false
19
- let activeFramework: Framework | undefined
20
- let activeShadow: ShadowRoot | undefined
21
-
22
- /**
23
- * Records a tool render failure: surfaces a banner and logs to the console. A consumer tool's
24
- * render failure is deliberately not routed through the client event bus, so a third-party tool
25
- * bug never reaches the platform's Sentry exception stream.
26
- *
27
- * @param {unknown} error - The error thrown or rejected by the framework renderer.
28
- * @example
29
- * handleRenderError(new Error('tool blew up'))
30
- */
31
- function handleRenderError(error: unknown) {
32
- renderFailed = true
33
- // eslint-disable-next-line no-console -- surface tool failures locally; consumer errors must not reach Sentry
34
- console.error(`Custom devtools tool "${tool.label}" failed to render`, error)
35
- }
36
-
37
- /**
38
- * Tears down the tool's mounted instance using the framework that rendered it. Idempotent: the
39
- * renderer's unmount is a no-op once the instance is gone, so calling it twice is safe.
40
- *
41
- * @example
42
- * teardown()
43
- */
44
- function teardown() {
45
- if (activeShadow && activeFramework?.unmount) {
46
- activeFramework.unmount(activeShadow)
47
- }
48
- }
49
-
50
- $: framework = $frameworkStore
51
-
52
- $: if (framework && host && !rendered) {
53
- rendered = true
54
- const shadow = host.shadowRoot ?? host.attachShadow({ mode: 'open' })
55
- const fw = framework
56
- activeFramework = fw
57
- activeShadow = shadow
58
- try {
59
- void Promise.resolve(fw.render(shadow, tool.component, client, experience))
60
- .then(() => {
61
- if (destroyed) teardown()
62
- })
63
- .catch(handleRenderError)
64
- } catch (error) {
65
- handleRenderError(error)
66
- }
67
- }
68
-
69
- onDestroy(() => {
70
- destroyed = true
71
- teardown()
72
- })
73
- </script>
74
-
75
- {#if framework}
76
- <div class="adapted-tool-host" bind:this={host} hidden={renderFailed}></div>
77
- {#if renderFailed}
78
- <div class="adapted-tool-fallback">
79
- <Banner status="error" title="Tool failed to render">
80
- The "{tool.label}" tool threw while rendering. See the browser console for details.
81
- </Banner>
82
- </div>
83
- {/if}
84
- {:else}
85
- <div class="adapted-tool-fallback">
86
- <Banner status="warning" title="Framework not registered">
87
- This tool renders a "{tool.component.frameworkName}" component, but no matching framework is
88
- registered with the Picked client. Add the corresponding framework plugin to use it.
89
- </Banner>
90
- </div>
91
- {/if}
92
-
93
- <style>
94
- .adapted-tool-host {
95
- height: 100%;
96
- padding: var(--space-4);
97
- box-sizing: border-box;
98
- }
99
-
100
- .adapted-tool-fallback {
101
- padding: var(--space-4);
102
- }
103
- </style>
@@ -1,27 +0,0 @@
1
- /** @file Registry helpers for the devtools "Custom Tools" tab — user-supplied, framework-adapted dev tools. */
2
- import type { AdaptedComponent, Picked } from '@picked/client';
3
- /**
4
- * A user-defined developer tool surfaced under the devtools "Custom Tools" tab.
5
- *
6
- * The component is framework-adapted (via `adaptReactComponent` or `adaptSvelteComponent`), so
7
- * tools can be authored in the host app's framework and still receive the live Picked client the
8
- * way an experience component does.
9
- */
10
- export interface CustomTool {
11
- id: string;
12
- label: string;
13
- component: AdaptedComponent;
14
- }
15
- /**
16
- * Reads the custom tools registered with the devtools plugin for a given client.
17
- *
18
- * Malformed entries are dropped, and entries that repeat an already-seen `id` are dropped
19
- * (first registration wins), so a single bad or duplicate registration can't break the tab — the
20
- * `id` is used as a keyed-each key when the tools are rendered as tabs.
21
- *
22
- * @param {Picked} client - The Picked client whose plugin config holds the registered tools.
23
- * @returns {CustomTool[]} The valid, id-unique registered custom tools, or an empty array when none exist.
24
- * @example
25
- * const tools = readCustomTools(getPicked())
26
- */
27
- export declare function readCustomTools(client: Picked): CustomTool[];
@@ -1 +0,0 @@
1
- import{DEVTOOLS_PLUGIN_NAME as e}from"./plugin.js";function t(e){return typeof e==`object`&&!!e&&`frameworkName`in e&&typeof e.frameworkName==`string`&&`component`in e}function n(e){return typeof e==`object`&&!!e&&`id`in e&&typeof e.id==`string`&&`label`in e&&typeof e.label==`string`&&`component`in e&&t(e.component)}function r(t){let r=t.getPluginConfig(e).customTools;if(!Array.isArray(r))return[];let i=new Set;return r.filter(n).filter(e=>!i.has(e.id)&&(i.add(e.id),!0))}export{r as readCustomTools};
@@ -1,160 +0,0 @@
1
- <script lang="ts">
2
- /** @file Devtools screen for the resolved Picked client configuration and reactive lifecycle state. */
3
- import { getPicked } from '../../../../hooks'
4
- import { Badge, Card, CodeBlock, DataTable, EmptyState, Stack, Text } from '../../ui'
5
-
6
- const client = getPicked()
7
- const lifecycleStageStore = client.lifecycleStageStore
8
- const readyStore = client.readyStore
9
- const preconditionPassedStore = client.preconditionPassedStore
10
- const conditionPassedStore = client.conditionPassedStore
11
-
12
- const searchParamEntries = Object.entries(client.searchParams ?? {}).map(([key, value]) => ({
13
- key,
14
- value: Array.isArray(value) ? value.join(', ') : String(value ?? ''),
15
- }))
16
-
17
- const staticRows = [
18
- { label: 'Project ID', value: client.projectId },
19
- { label: 'API URL', value: client.apiUrl },
20
- { label: 'Dashboard URL', value: client.dashboardUrl },
21
- { label: 'Documentation URL', value: client.documentationSiteUrl },
22
- { label: 'Data source', value: client.dataSource === null ? '—' : JSON.stringify(client.dataSource) },
23
- {
24
- label: 'Version skew',
25
- value:
26
- client.versionSkew === null
27
- ? '—'
28
- : `snapshot ${client.versionSkew.seeded} kept over resolved ${client.versionSkew.resolved}`,
29
- },
30
- ]
31
-
32
- const configColumns = [
33
- { key: 'label', header: 'Property' },
34
- { key: 'value', header: 'Value' },
35
- ]
36
-
37
- const searchParamColumns = [
38
- { key: 'key', header: 'Key' },
39
- { key: 'value', header: 'Value' },
40
- ]
41
-
42
- /**
43
- * Maps a lifecycle stage to a Badge status colour.
44
- *
45
- * @param {'idle' | 'starting' | 'ready' | 'failed'} stage - The current lifecycle stage.
46
- * @returns {'default' | 'info' | 'success' | 'error'} The Badge status variant.
47
- * @example
48
- * ```typescript
49
- * stageStatus('ready') // 'success'
50
- * ```
51
- */
52
- function stageStatus(
53
- stage: 'idle' | 'starting' | 'ready' | 'failed',
54
- ): 'default' | 'info' | 'success' | 'error' {
55
- if (stage === 'ready') return 'success'
56
- if (stage === 'starting') return 'info'
57
- if (stage === 'failed') return 'error'
58
- return 'default'
59
- }
60
-
61
- /**
62
- * Maps a tri-state boolean gate result to a Badge status colour.
63
- *
64
- * @param {boolean | undefined} value - The gate value: true (passed), false (blocked), or undefined (unevaluated).
65
- * @returns {'default' | 'success' | 'error'} The Badge status variant.
66
- * @example
67
- * ```typescript
68
- * gateStatus(undefined) // 'default'
69
- * gateStatus(true) // 'success'
70
- * ```
71
- */
72
- function gateStatus(value: boolean | undefined): 'default' | 'success' | 'error' {
73
- if (value === true) return 'success'
74
- if (value === false) return 'error'
75
- return 'default'
76
- }
77
-
78
- /**
79
- * Renders a tri-state boolean gate as a short label.
80
- *
81
- * @param {boolean | undefined} value - The gate value.
82
- * @returns {string} The label text.
83
- * @example
84
- * ```typescript
85
- * gateLabel(undefined) // 'pending'
86
- * ```
87
- */
88
- function gateLabel(value: boolean | undefined): string {
89
- if (value === true) return 'passed'
90
- if (value === false) return 'blocked'
91
- return 'pending'
92
- }
93
- </script>
94
-
95
- <Stack direction="vertical" gap="medium" padding="medium">
96
- <Text size="caption" color="subdued">
97
- The resolved configuration and live lifecycle state for this Picked client instance.
98
- </Text>
99
-
100
- <Card sectioned>
101
- {#snippet header()}
102
- <Text size="caption" weight="semibold" color="subdued">CONFIGURATION</Text>
103
- {/snippet}
104
- <DataTable columns={configColumns} rows={staticRows}>
105
- {#snippet row(item)}
106
- <tr>
107
- <td><Text size="small" weight="medium">{item.label}</Text></td>
108
- <td><CodeBlock code={item.value} inline /></td>
109
- </tr>
110
- {/snippet}
111
- </DataTable>
112
- </Card>
113
-
114
- <Card sectioned>
115
- {#snippet header()}
116
- <Text size="caption" weight="semibold" color="subdued">LIFECYCLE</Text>
117
- {/snippet}
118
- <Stack direction="vertical" gap="small" padding="medium">
119
- <Stack direction="horizontal" gap="small">
120
- <Text size="small" weight="medium">Stage:</Text>
121
- <Badge status={stageStatus($lifecycleStageStore)} size="small">{$lifecycleStageStore}</Badge>
122
- </Stack>
123
- <Stack direction="horizontal" gap="small">
124
- <Text size="small" weight="medium">Ready:</Text>
125
- <Badge status={$readyStore ? 'success' : 'default'} size="small">{$readyStore ? 'true' : 'false'}</Badge>
126
- </Stack>
127
- <Stack direction="horizontal" gap="small">
128
- <Text size="small" weight="medium">Precondition:</Text>
129
- <Badge status={gateStatus($preconditionPassedStore)} size="small">
130
- {gateLabel($preconditionPassedStore)}
131
- </Badge>
132
- </Stack>
133
- <Stack direction="horizontal" gap="small">
134
- <Text size="small" weight="medium">Condition:</Text>
135
- <Badge status={gateStatus($conditionPassedStore)} size="small">
136
- {gateLabel($conditionPassedStore)}
137
- </Badge>
138
- </Stack>
139
- </Stack>
140
- </Card>
141
-
142
- <Card sectioned>
143
- {#snippet header()}
144
- <Text size="caption" weight="semibold" color="subdued">
145
- PICKED SEARCH PARAMS ({searchParamEntries.length})
146
- </Text>
147
- {/snippet}
148
- <DataTable columns={searchParamColumns} rows={searchParamEntries}>
149
- {#snippet row(entry)}
150
- <tr>
151
- <td><CodeBlock code={entry.key} inline /></td>
152
- <td><CodeBlock code={entry.value} inline /></td>
153
- </tr>
154
- {/snippet}
155
- {#snippet empty()}
156
- <EmptyState message="No picked-* search params on the current URL" />
157
- {/snippet}
158
- </DataTable>
159
- </Card>
160
- </Stack>
@@ -1,89 +0,0 @@
1
- <script lang="ts">
2
- /** @file Devtools screen listing CMS content records registered with the client. */
3
- import type { Content } from '@picked/client'
4
- import { getPicked } from '../../../../hooks'
5
- import { Badge, Card, CodeBlock, DataTable, EmptyState, ExpandableRow, Stack, Text } from '../../ui'
6
-
7
- const client = getPicked()
8
- const contentsStore = client.contents.listStore
9
-
10
- let expandedId: string | null = null
11
-
12
- const columns = [
13
- { key: 'id', header: 'ID' },
14
- { key: 'keys', header: 'Top-level keys' },
15
- ]
16
-
17
- /**
18
- * Returns the top-level keys of a content record's `data` object, used to give a quick
19
- * shape preview in the row summary without expanding.
20
- *
21
- * @param {Content} content - The content record.
22
- * @returns {string[]} The data object's top-level keys.
23
- * @example
24
- * ```typescript
25
- * dataKeys({ id: 'c1', data: { headline: 'hi' } }) // ['headline']
26
- * ```
27
- */
28
- function dataKeys(content: Content): string[] {
29
- return Object.keys(content.data ?? {})
30
- }
31
-
32
- /**
33
- * Pretty-prints the content record's `data` object for use inside a multi-line CodeBlock.
34
- *
35
- * @param {Content} content - The content record.
36
- * @returns {string} A two-space-indented JSON representation of `data`.
37
- * @example
38
- * ```typescript
39
- * formatData({ id: 'c1', data: { a: 1 } }) // '{\n "a": 1\n}'
40
- * ```
41
- */
42
- function formatData(content: Content): string {
43
- return JSON.stringify(content.data, null, 2)
44
- }
45
- </script>
46
-
47
- <Stack direction="vertical" gap="medium" padding="medium">
48
- <Text size="caption" color="subdued">
49
- Content records registered with the client by the active content loader.
50
- </Text>
51
-
52
- <Card sectioned>
53
- <DataTable {columns} rows={$contentsStore}>
54
- {#snippet row(content)}
55
- {@const expanded = expandedId === content.id}
56
- {@const keys = dataKeys(content)}
57
- <ExpandableRow
58
- {expanded}
59
- onToggle={() => { expandedId = expanded ? null : content.id }}
60
- colspan={columns.length}
61
- >
62
- {#snippet summary()}
63
- <td><CodeBlock code={content.id} inline /></td>
64
- <td>
65
- {#if keys.length > 0}
66
- <Stack direction="horizontal" gap="small" wrap={true}>
67
- {#each keys as key (key)}
68
- <Badge status="default" size="small">{key}</Badge>
69
- {/each}
70
- </Stack>
71
- {:else}
72
- <Text size="small" color="subdued">—</Text>
73
- {/if}
74
- </td>
75
- {/snippet}
76
- {#snippet details()}
77
- <Stack direction="vertical" gap="small">
78
- <Text size="caption" weight="semibold" color="subdued">DATA</Text>
79
- <CodeBlock code={formatData(content)} />
80
- </Stack>
81
- {/snippet}
82
- </ExpandableRow>
83
- {/snippet}
84
- {#snippet empty()}
85
- <EmptyState message="No content registered" />
86
- {/snippet}
87
- </DataTable>
88
- </Card>
89
- </Stack>
@@ -1,29 +0,0 @@
1
- <script lang="ts">
2
- /** @file Screen hosting user-registered custom devtools tools as nested tabs. */
3
- import { getPicked } from '../../../../hooks'
4
- import AdaptedToolHost from '../../components/AdaptedToolHost.svelte'
5
- import Tabs from '../../components/Tabs.svelte'
6
- import { readCustomTools } from '../../customTools'
7
- import { Button, EmptyState, Stack } from '../../ui'
8
-
9
- const client = getPicked()
10
- const docsUrl = `${client.documentationSiteUrl}/chrome-extension#custom-tools`
11
- const tools = readCustomTools(client)
12
- const tabs = tools.map((tool) => ({
13
- id: tool.id,
14
- label: tool.label,
15
- component: AdaptedToolHost,
16
- props: { tool },
17
- }))
18
- </script>
19
-
20
- {#if tabs.length > 0}
21
- <Tabs {tabs} />
22
- {:else}
23
- <Stack direction="vertical" gap="medium" padding="medium" justify="center">
24
- <EmptyState message="No custom tools registered." />
25
- <Button variant="ghost" size="small" href={docsUrl} target="_blank">
26
- Learn how to add custom tools
27
- </Button>
28
- </Stack>
29
- {/if}