dsh-quick-actions 0.1.0 → 0.2.0-rc.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.
@@ -25,6 +25,8 @@ export type SurfaceDensity = 'wide' | 'narrow';
25
25
  */
26
26
  export declare const NARROW_SURFACE_WIDTH = 480;
27
27
  export declare function densityFor(width: number): SurfaceDensity;
28
+ /** How far, in CSS px, a control may overrun the bar row and still count as fitting. */
29
+ export declare const FIT_TOLERANCE = 0.5;
28
30
  /** One measured row of the `bar` layout. */
29
31
  export interface BarFitInput {
30
32
  /** Usable inner width of the action row. */
@@ -45,5 +47,10 @@ export interface BarFitInput {
45
47
  * no layout — every width reads as zero. That answers "all of them": showing the
46
48
  * full row and letting the browser's own overflow handle it for one frame is
47
49
  * better than flashing a "more" button that the next frame withdraws.
50
+ *
51
+ * A control fits when it overruns the row by less than `FIT_TOLERANCE`. Whenever
52
+ * the bar is content-sized (spec 22.9) the row it measures is exactly as wide as
53
+ * the controls it shows, and fractional layout can report that a hair short;
54
+ * folding a face over the difference would narrow the row and start a cascade.
48
55
  */
49
56
  export declare function fitActionCount(input: BarFitInput): number;
@@ -1,38 +1,35 @@
1
1
  import type { CanonicalRewriteOutcome, SettingsRewriteProvider } from './settings.js';
2
2
  import type { PresetCatalog } from '../model/index.js';
3
3
  /**
4
- * The read-only catalog projection published to Clients (spec 6.2, 17.2). It is
5
- * the catalog itself under the name the spec gives it — one shape, so the Host
6
- * cannot publish something the model never validated.
4
+ * The read-only catalog projection (spec 6.2). It is the catalog itself under
5
+ * the name the spec gives it — one shape, so the Host cannot publish something
6
+ * the model never validated.
7
7
  */
8
8
  export type CatalogSnapshot = PresetCatalog;
9
- /**
10
- * The Host settings provider as this plugin uses it: namespace registration plus
11
- * the fenced write face. Declared structurally so the Host is testable against a
12
- * controlled fake; the real `SettingsProvider` satisfies it.
13
- */
14
- export interface QuickActionsSettingsProvider extends SettingsRewriteProvider {
15
- register(ns: string, schema: unknown, options?: unknown): unknown;
16
- }
9
+ /** The Host settings provider as this plugin uses it; the real `SettingsForms` satisfies it. */
10
+ export type QuickActionsSettingsProvider = SettingsRewriteProvider;
17
11
  /** The running Host, owned by the fiber that started it. */
18
12
  export interface QuickActionsHost {
19
- /** Settles when the startup canonical rewrite has been attempted. */
20
- readonly ready: Promise<CanonicalRewriteOutcome>;
21
13
  /**
22
- * The read-only Remote payload (spec 6.2): lossless JSON, no Settings CRUD.
23
- * Each call hands back a detached copy, so a consumer cannot reach the
24
- * authoritative catalog through the value it was given.
14
+ * The authoritative catalog as lossless JSON. Each call hands back a detached
15
+ * copy, so a consumer cannot reach the authoritative catalog through the value
16
+ * it was given.
25
17
  */
26
18
  describeCatalog(): Promise<CatalogSnapshot>;
19
+ /**
20
+ * Canonicalize the stored section against this catalog (spec 6.3). Only
21
+ * meaningful once the entry is active: before that the provider does not
22
+ * serve the form, and the answer is `unregistered`.
23
+ */
24
+ canonicalize(settings: QuickActionsSettingsProvider): Promise<CanonicalRewriteOutcome>;
27
25
  }
28
26
  /**
29
- * Load the catalog, register both namespaces and canonicalize the stored section.
27
+ * Load and validate the catalog.
30
28
  *
31
- * An invalid preset configuration throws before anything is registered: the
32
- * catalog is author-owned, so a mistake fails plugin loading rather than
33
- * silently shipping a partial catalog (spec 5.1).
29
+ * An invalid preset configuration throws: the catalog is author-owned, so a
30
+ * mistake fails plugin loading rather than silently shipping a partial catalog
31
+ * (spec 5.1).
34
32
  *
35
- * @param settings - the Host settings provider.
36
33
  * @param config - the Host composition entry's config.
37
34
  */
38
- export declare function startQuickActionsHost(settings: QuickActionsSettingsProvider, config: unknown): QuickActionsHost;
35
+ export declare function startQuickActionsHost(config: unknown): QuickActionsHost;
@@ -1,67 +1,82 @@
1
1
  /**
2
- * The single persisted Settings namespace and the Host's canonical rewrite
3
- * (spec 4.2, 6.1, 6.3).
2
+ * The plugin's Config — which since DSH 0.1.7 *is* its Settings form — and the
3
+ * Host's canonical rewrite (spec 4.2, 6.1, 6.3, 22).
4
4
  *
5
- * The Host is the sole validation and migration authority, so the registered
6
- * schema is deliberately permissive: it fixes the shape of the section and its
7
- * defaults, and nothing else. A strict schema would refuse registration for a
8
- * section a higher version wrote — which is exactly the data spec 5.3 requires
9
- * to survive a downgrade untouched. The shared model decodes and normalizes what
10
- * the schema lets through, and it never rewrites content it cannot render.
5
+ * The Host is the sole validation and migration authority, so the schema is
6
+ * deliberately permissive: it fixes the shape of the section and its defaults,
7
+ * and nothing else. A strict schema would refuse a section a higher version
8
+ * wrote — which is exactly the data spec 5.3 requires to survive a downgrade
9
+ * untouched. The shared model decodes and normalizes what the schema lets
10
+ * through, and it never rewrites content it cannot render.
11
11
  */
12
12
  import Schema from '@deepseek-ai/schemastery';
13
13
  import type { PresetCatalog, QuickActionSettingsV1 } from '../model/index.js';
14
14
  /**
15
- * Shape and defaults of the persisted section (spec 4.2). The three collections
16
- * stay unconstrained on purpose: a stricter schema would refuse registration for
17
- * a section this release cannot render, and refusing registration is how stored
18
- * data gets lost. The shared model is the validation gate — see the module note.
19
- */
20
- export declare const quickActionSettingsSchema: Schema<Schemastery.ObjectS<{
21
- schemaVersion: Schema<number, number>;
22
- layout: Schema<string, string>;
23
- userActionsById: Schema<any, any>;
24
- actionOrder: Schema<any, any>;
25
- presetStateById: Schema<any, any>;
26
- }>, Schemastery.ObjectT<{
27
- schemaVersion: Schema<number, number>;
28
- layout: Schema<string, string>;
29
- userActionsById: Schema<any, any>;
30
- actionOrder: Schema<any, any>;
31
- presetStateById: Schema<any, any>;
32
- }>>;
33
- /**
34
- * Shape of the catalog namespace. Its authoritative content is the composition
35
- * `base` layer the Host declares; a user layer is never written and, if one were
36
- * hand-written into the document, Clients would still read `base` (spec 17.2).
15
+ * The plugin Config (spec 22.2). Every field is `volatile`, because DSH lets a
16
+ * Settings form — and so the Client — reach volatile fields only.
17
+ *
18
+ * - The five user-state fields are top-level on purpose: the DSH legacy import
19
+ * moves an old `settings.yaml` section into the entry of the same id key by
20
+ * key, and refuses the whole section when any top-level key is not a volatile
21
+ * field. This exact shape is what lets that one-shot import land.
22
+ * - `presets` is the author's list merged behind the built-ins (spec 5.1). It
23
+ * is volatile only so the Client can read it — a non-volatile field never
24
+ * reaches the browser — and nothing in this plugin ever writes it.
25
+ *
26
+ * The collections stay unconstrained: a stricter schema would refuse a section
27
+ * this release cannot render, and refusing it is how stored data gets lost.
37
28
  */
38
- export declare const quickActionCatalogSchema: Schema<Schemastery.ObjectS<{
39
- schemaVersion: Schema<number, number>;
40
- revision: Schema<string, string>;
41
- presets: Schema<any, any>;
42
- }>, Schemastery.ObjectT<{
43
- schemaVersion: Schema<number, number>;
44
- revision: Schema<string, string>;
45
- presets: Schema<any, any>;
46
- }>>;
47
- /** One namespace as the provider describes it. */
29
+ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
30
+ presets: Schema<any, any, "volatile-defined">;
31
+ schemaVersion: Schema<number, number, "volatile-defined">;
32
+ layout: Schema<string, string, "volatile-defined">;
33
+ userActionsById: Schema<any, any, "volatile-defined">;
34
+ actionOrder: Schema<any, any, "volatile-defined">;
35
+ presetStateById: Schema<any, any, "volatile-defined">;
36
+ }>>, Schemastery.ObjectT<NoInfer<{
37
+ presets: Schema<any, any, "volatile-defined">;
38
+ schemaVersion: Schema<number, number, "volatile-defined">;
39
+ layout: Schema<string, string, "volatile-defined">;
40
+ userActionsById: Schema<any, any, "volatile-defined">;
41
+ actionOrder: Schema<any, any, "volatile-defined">;
42
+ presetStateById: Schema<any, any, "volatile-defined">;
43
+ }>>, "plain">;
44
+ /** One path-addressed field write, as the settings provider takes it. */
45
+ export interface SettingsSetOp {
46
+ readonly op: 'set';
47
+ readonly path: readonly string[];
48
+ readonly value: unknown;
49
+ }
50
+ /** One form as the provider describes it. */
48
51
  export interface SettingsDescriptorLike {
49
52
  readonly ns: string;
50
- /** Monotonic revision of the raw user section; send it back to fence a write. */
53
+ /** Monotonic revision of the raw entry configuration; send it back to fence a write. */
51
54
  readonly revision: number;
52
- /** The raw stored user section, absent while nothing was ever written. */
55
+ /** The form fields the active profile patch sets. */
53
56
  readonly user?: unknown;
54
57
  }
55
58
  /**
56
59
  * The part of the Host settings provider the canonical rewrite reads and writes
57
60
  * through. Declared structurally so the rewrite is testable against a controlled
58
- * fake — the real `SettingsProvider` satisfies it as-is.
61
+ * fake — the real `SettingsForms` satisfies it as-is.
59
62
  */
60
63
  export interface SettingsRewriteProvider {
61
64
  readonly writable: boolean;
62
65
  describe(): readonly SettingsDescriptorLike[];
63
- replace(ns: string, section: object, expectedRevision?: number): Promise<void>;
66
+ mutate(ns: string, ops: readonly SettingsSetOp[], expectedRevision?: number): Promise<void>;
64
67
  }
68
+ /**
69
+ * One write per user-state field, never touching `presets`: the author's list
70
+ * shares the entry's config, and a write that restated it would pin whatever it
71
+ * read into the profile layer.
72
+ */
73
+ export declare function stateOps(section: QuickActionSettingsV1): readonly SettingsSetOp[];
74
+ /**
75
+ * The user-state fields the profile layer actually sets, or `undefined` when it
76
+ * sets none. The same layer may carry the author's `presets`; those are Config,
77
+ * not stored state, so a profile holding only presets has nothing stored.
78
+ */
79
+ export declare function storedState(user: unknown): Readonly<Record<string, unknown>> | undefined;
65
80
  export type CanonicalRewriteOutcome =
66
81
  /** The stored section already was canonical; nothing was written. */
67
82
  {
@@ -90,7 +105,7 @@ export type CanonicalRewriteOutcome =
90
105
  } | {
91
106
  readonly status: 'read-only';
92
107
  }
93
- /** The namespace is not registered yet, so there is nothing to fence a write to. */
108
+ /** The form is not served — the entry is not active — so there is nothing to fence a write to. */
94
109
  | {
95
110
  readonly status: 'unregistered';
96
111
  };
@@ -99,9 +114,9 @@ export type CanonicalRewriteOutcome =
99
114
  * persist it behind the revision it was read at (spec 6.3).
100
115
  *
101
116
  * Nothing is written when nothing is stored: materializing the defaults into the
102
- * user layer would shadow the composition `base` and destroy what `replace({})`
103
- * resets to. Nothing is written for a higher `schemaVersion` either — that data
104
- * belongs to the version that wrote it.
117
+ * profile layer would shadow every layer below it for good. Nothing is written
118
+ * for a higher `schemaVersion` either — that data belongs to the version that
119
+ * wrote it.
105
120
  *
106
121
  * A conflict means another writer won the race, so the rewrite refreshes the
107
122
  * authoritative snapshot and recomputes rather than replaying its own stale
@@ -1,31 +1,33 @@
1
1
  /**
2
2
  * Host composition entry for Composer Quick Actions.
3
3
  *
4
- * `settings` is a hard dependency: the concrete provider (`dsh-settings-file`)
5
- * *is* the service, so injecting it is how this plugin waits for the backend
6
- * instead of inventing an in-memory, browser or private-file store (spec 6.1).
7
- * A provider that is present but not writable is a supported state, not a
8
- * missing one — the stored section is left untouched and the surfaces go
9
- * read-only (spec 10).
4
+ * Since DSH 0.1.7 the stored section is this entry's own Config (spec 22): the
5
+ * exported `Config` declares it, the Loader hands it over, and DSH Settings
6
+ * reads and writes it through the active profile. There is no namespace to
7
+ * register and no second namespace for the catalog.
10
8
  *
11
- * Everything this entry registers — the Settings namespace and the startup
12
- * rewrite's reporting — is owned by this fiber and withdrawn when it unloads.
13
- * The user's stored section deliberately survives unload, so reinstalling
14
- * restores the user's actions.
9
+ * `settings` is therefore an optional dependency, as for every first-party
10
+ * plugin: the Quick Actions run without it, and while it is present this entry
11
+ * opts out of an auto-generated Settings page — the plugin ships its own
12
+ * management panel — and canonicalizes the stored section once every entry of
13
+ * the profile has settled.
14
+ *
15
+ * Everything this entry installs is owned by this fiber and withdrawn when it
16
+ * unloads. The user's stored section deliberately survives unload, so
17
+ * reinstalling restores the user's actions.
15
18
  *
16
19
  * The public surface is the plugin contract only. The shared model, the
17
20
  * Settings rewrite and the catalog assembly stay internal to the package
18
- * (spec 11.2); whether any of them becomes a published runtime export belongs
19
- * to the release-surface decision.
21
+ * (spec 11.2).
20
22
  */
21
23
  import type { Context } from '@deepseek-ai/cordis';
22
24
  import type { QuickActionsHost } from './host/index.js';
23
25
  export declare const name = "composer-quick-actions";
24
- export declare const inject: readonly string[];
26
+ export { Config } from './host/settings.js';
25
27
  export type { ComposerQuickActionsConfig } from './host/config.js';
26
28
  export type { CatalogSnapshot, QuickActionsHost } from './host/index.js';
27
29
  /**
28
- * Load the Preset Catalog, register the Settings namespace and canonicalize the
30
+ * Load the Preset Catalog and, while Settings is present, canonicalize the
29
31
  * stored section. An invalid preset configuration throws here, failing plugin
30
32
  * loading loudly rather than shipping a partial catalog (spec 5.1).
31
33
  *
@@ -3,11 +3,11 @@ import type { PresetQuickAction, QuickActionField, QuickActionIssueReason } from
3
3
  export declare const QUICK_ACTION_CATALOG_LIMIT = 50;
4
4
  /** Where a catalog entry was declared. */
5
5
  export type PresetSource = 'builtin' | 'config';
6
- /** What the Host feeds the model: raw JSON, validated here rather than upstream. */
6
+ /** What either face feeds the model: raw JSON, validated here rather than upstream. */
7
7
  export interface PresetCatalogInput {
8
8
  /** The package's built-in manifest, in declaration order. */
9
9
  readonly builtins: readonly unknown[];
10
- /** `Config.presets` from the Host composition, in declaration order. */
10
+ /** The `presets` Config field, in declaration order. */
11
11
  readonly configured: readonly unknown[];
12
12
  }
13
13
  /** One reason the plugin config must fail to load. */
@@ -25,7 +25,7 @@ export type PresetCatalogIssue = {
25
25
  readonly count: number;
26
26
  readonly limit: number;
27
27
  };
28
- /** The authoritative, read-only catalog snapshot the Remote publishes (spec 6.2). */
28
+ /** The authoritative, read-only Preset Catalog (spec 6.2): what the Host validates and the Client rebuilds (spec 22.3). */
29
29
  export interface PresetCatalog {
30
30
  readonly schemaVersion: 1;
31
31
  /** Determined by the catalog projection; any change to it changes this value. */
@@ -46,18 +46,3 @@ export type PresetCatalogResult = {
46
46
  * author got wrong, so the mistake surfaces at startup rather than at send time.
47
47
  */
48
48
  export declare function buildPresetCatalog(input: PresetCatalogInput): PresetCatalogResult;
49
- /**
50
- * Read one published catalog snapshot back (spec 17.2). The Host is the catalog's
51
- * single validation authority, so this is a defensive decode of an already
52
- * confirmed snapshot rather than a second authority — but it is a decode, not a
53
- * cast: a snapshot this release cannot read in full yields no catalog at all.
54
- *
55
- * All-or-nothing on purpose. Dropping the entries it cannot read would show the
56
- * user a silently truncated action list, which is exactly what spec 5.1 forbids
57
- * the Host to do; the consumer reports a catalog error instead (spec 10).
58
- *
59
- * The Host's `revision` is carried through rather than recomputed. It is the
60
- * catalog's published identity, and a Client that recomputed it would be
61
- * asserting an authority it does not have.
62
- */
63
- export declare function decodeCatalogSnapshot(raw: unknown): PresetCatalog | undefined;
@@ -7,6 +7,7 @@ export * from './json.js';
7
7
  export * from './text.js';
8
8
  export * from './validation.js';
9
9
  export * from './catalog.js';
10
+ export * from './presets.js';
10
11
  export * from './settings.js';
11
12
  export * from './normalize.js';
12
13
  export * from './projection.js';
@@ -3,6 +3,11 @@
3
3
  * Preset Catalog (spec 5.1), declared ahead of the Host composition's
4
4
  * `Config.presets`.
5
5
  *
6
+ * It lives in the shared model because both faces merge it: the Host validates
7
+ * the catalog at load, and the Client rebuilds the same catalog from this list
8
+ * plus the `presets` form field it reads (spec 22.3). One list, so the two can
9
+ * never disagree about what the built-ins are.
10
+ *
6
11
  * These are author-facing product copy in one language; changing a label or a
7
12
  * text is a product decision, not an implementation one.
8
13
  *
@@ -1,16 +1,20 @@
1
1
  import type { CustomQuickActionValue, PresetQuickActionState, QuickActionSettingsV1, QuickActionTombstone, StoredQuickActionValue } from './types.js';
2
2
  /**
3
- * The one namespace holding user data (spec 4.2); renaming it orphans every
4
- * stored section. It lives in the shared model because both faces address it:
5
- * the Host registers it, the Client binds the same name.
3
+ * The one namespace holding user data (spec 4.2, 22); renaming it orphans every
4
+ * stored section. Since DSH 0.1.7 a Settings namespace *is* a profile entry id,
5
+ * so this is also the Cordis loader entry id the bundle patch inserts — the two
6
+ * can no longer drift apart. It lives in the shared model because both faces
7
+ * address it: the Host describes and fences its canonical rewrite against it,
8
+ * the Client reads and writes the same form.
6
9
  */
7
10
  export declare const QUICK_ACTIONS_SETTINGS_NAMESPACE = "composer-quick-actions";
8
11
  /**
9
- * The read-only namespace carrying the Preset Catalog to Clients (spec 17.2).
10
- * The plugin never writes its user layer, so it holds no persisted section —
11
- * `composer-quick-actions` remains the only persisted namespace (spec 4.2).
12
+ * The top-level fields of the stored section, in canonical order (spec 4.2).
13
+ * Each is a separate volatile Config field (spec 22.2): the DSH legacy import
14
+ * addresses a section by these exact top-level keys, and every write sets them
15
+ * field by field so a write never reaches the author's `presets`.
12
16
  */
13
- export declare const QUICK_ACTIONS_CATALOG_NAMESPACE = "composer-quick-actions-catalog";
17
+ export declare const QUICK_ACTION_STATE_FIELDS: readonly ["schemaVersion", "layout", "userActionsById", "actionOrder", "presetStateById"];
14
18
  /** The state a fresh install starts from (spec 4.2). */
15
19
  export declare const DEFAULT_QUICK_ACTION_SETTINGS: QuickActionSettingsV1;
16
20
  /**
@@ -11,22 +11,26 @@
11
11
  * Colours are DSH alias theme tokens only — nothing here defines a palette, and
12
12
  * nothing overrides a global theme (spec 8.4).
13
13
  *
14
- * ## The width rule (spec 8.2)
14
+ * ## The width rule (spec 8.2, 22.9)
15
15
  *
16
- * The two layouts sit in different boxes, so they reach the same outer edges by
17
- * different arithmetic:
16
+ * `.dsh-cqa-ribbon` (and the launcher, in the same box) renders in the composer
17
+ * stack, outside the InputBar, which is the element that owns
18
+ * `--dsh-composer-side-clearance` as padding. It therefore subtracts that
19
+ * clearance from both sides itself, is capped at `--dsh-composer-card-max-width`
20
+ * — the same cap the composer card uses — and is centred, so its left and right
21
+ * edges coincide with the input box exactly rather than approximately.
18
22
  *
19
- * - `.dsh-cqa-ribbon` renders in the composer stack, outside the InputBar, which
20
- * is the element that owns `--dsh-composer-side-clearance` as padding. It
21
- * therefore subtracts that clearance from both sides itself.
22
- * - `.dsh-cqa-bar` renders as the InputBar's last child, inside that padding, so
23
- * it is simply `100%` wide.
24
- *
25
- * Both are then capped at `--dsh-composer-card-max-width` — the same cap the
26
- * composer card uses — and centred, so their left and right edges coincide with
27
- * the input box exactly rather than approximately.
23
+ * `.dsh-cqa-bar` makes no such claim. Since DSH 0.1.6-alpha.2 the composer dock is
24
+ * a row under the card that DSH centres and sizes to its content, shared with
25
+ * DSH's own stats pills and context meter, so the bar is a content-sized member of
26
+ * that row (spec 22.9). It only has to stay inside it: `min-width: 0` lets it
27
+ * shrink when the row reaches the composer's width, which is what hands the
28
+ * overflow split a smaller region to fold into "more". Once it folds it claims
29
+ * the card's width (`[data-quick-actions-overflow]`), capped by the row's own
30
+ * `max-width: 100%`: content-sized, the region the split measures would only be
31
+ * as wide as what it already shows, and a wider window could never unfold it.
28
32
  */
29
- export declare const QUICK_ACTIONS_CSS = "\n.dsh-cqa-ribbon,\n.dsh-cqa-launcher {\n box-sizing: border-box;\n width: calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance));\n max-width: var(--dsh-composer-card-max-width);\n margin: 0 auto;\n}\n.dsh-cqa-bar {\n box-sizing: border-box;\n width: 100%;\n max-width: var(--dsh-composer-card-max-width);\n margin: 0 auto;\n}\n\n.dsh-cqa-row {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n padding: 2px 0;\n}\n.dsh-cqa-row[data-density='narrow'] {\n gap: 6px;\n}\n\n.dsh-cqa-title {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n white-space: nowrap;\n}\n\n/* The ribbon overflows horizontally; the management entry never scrolls away. */\n.dsh-cqa-scroll {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: thin;\n}\n.dsh-cqa-fit {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n}\n.dsh-cqa-trailing {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n margin-left: auto;\n}\n\n/*\n * The capsule itself \u2014 height, radius, padding, colours, hover and \":disabled\"\n * \u2014 belongs to the official \"Button\". What is left here is what a shared\n * control cannot know (how it behaves inside these rows) plus what the\n * primitive does not supply. Nothing below may restate a Button property,\n * because the plugin class is applied after the primitive's and would win on\n * equal specificity.\n *\n * The focus ring is one of the things it does not supply: \"Button.module.css\"\n * and \"Pill.module.css\" carry no \":focus\" rule at all \u2014 the library leaves the\n * ring to each component that wants one (\"Input.module.css\" has\n * \":focus-within\", \"HoverCard\" and \"JsonTree\" their own). Spec 8.4 makes a\n * clear focus ring a hard gate, so it stays here for every control this plugin\n * renders.\n */\n.dsh-cqa-action,\n.dsh-cqa-entry {\n /* No global border-box reset exists in this stylesheet, and Button pads\n itself, so the cap has to count that padding to mean 240px on screen. */\n box-sizing: border-box;\n flex: none;\n /* Long labels truncate rather than pushing the row's other controls out. */\n max-width: 240px;\n}\n.dsh-cqa-action:focus-visible,\n.dsh-cqa-entry:focus-visible {\n outline: 2px solid var(--dsw-alias-state-business-primary);\n outline-offset: 1px;\n}\n/* \"aria-disabled\" is not \":disabled\": a control kept focusable while a write is\n in flight still has to read as inert, and no primitive expresses that. */\n.dsh-cqa-entry[aria-disabled='true'] {\n opacity: 0.5;\n cursor: default;\n}\n/* The searchable panel's rows stay native \u2014 a full-width, left-aligned list row\n is not a capsule \u2014 so they still need a focus ring of their own. */\n.dsh-cqa-panel-item:focus-visible,\n.dsh-cqa-link:focus-visible {\n outline: 2px solid var(--dsw-alias-state-business-primary);\n outline-offset: 1px;\n}\n.dsh-cqa-label {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-cqa-icon {\n flex: none;\n}\n/* The chip look is \"Pill\"'s; only its behaviour in a flex row is ours. */\n.dsh-cqa-badge,\n.dsh-cqa-tag {\n flex: none;\n}\n\n.dsh-cqa-note {\n box-sizing: border-box;\n width: 100%;\n margin: 4px 0 0;\n padding: 4px 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-cqa-note-text {\n flex: 1 1 auto;\n min-width: 0;\n}\n.dsh-cqa-link {\n flex: none;\n border: 0;\n background: none;\n padding: 0;\n color: var(--dsw-alias-state-business-primary);\n font: inherit;\n font-size: 12px;\n cursor: pointer;\n text-decoration: underline;\n}\n\n/* Anchored surfaces: the popover list and the confirmation panel. */\n.dsh-cqa-anchor {\n position: relative;\n}\n.dsh-cqa-backdrop {\n position: fixed;\n z-index: 19;\n inset: 0;\n}\n.dsh-cqa-panel {\n position: absolute;\n z-index: 20;\n bottom: calc(100% + 6px);\n left: 0;\n box-sizing: border-box;\n max-width: min(100%, 360px);\n min-width: 220px;\n max-height: 260px;\n overflow-y: auto;\n padding: 6px;\n border: 0.5px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-specific-tip);\n box-shadow: var(--dsw-elevation-soft);\n}\n.dsh-cqa-panel-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-cqa-panel-head .dsh-cqa-panel-title {\n flex: 1 1 auto;\n min-width: 0;\n}\n.dsh-cqa-panel-title {\n padding: 4px 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n.dsh-cqa-panel-item {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 6px 8px;\n border: 0;\n border-radius: 8px;\n background: none;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n text-align: left;\n cursor: pointer;\n}\n.dsh-cqa-panel-item:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-cqa-panel-item:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.dsh-cqa-confirm-text {\n margin: 6px 0;\n padding: 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code);\n font-size: 12px;\n line-height: 18px;\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 160px;\n overflow-y: auto;\n}\n.dsh-cqa-confirm-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n\n/* ------------------------------------------------------------------------- */\n/* Fields, shared by the search box and the Custom Quick Action form */\n/* ------------------------------------------------------------------------- */\n\n.dsh-cqa-field {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 4px 0;\n}\n.dsh-cqa-field-label {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n}\n.dsh-cqa-field-hint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n.dsh-cqa-field-error {\n color: var(--dsw-alias-state-danger-primary, var(--dsw-alias-label-primary));\n font-size: 11px;\n line-height: 16px;\n font-weight: 500;\n}\n\n.dsh-cqa-input,\n.dsh-cqa-textarea {\n box-sizing: border-box;\n width: 100%;\n padding: 4px 8px;\n border: 0.5px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n}\n.dsh-cqa-textarea {\n resize: vertical;\n min-height: 72px;\n font-family: var(--ds-font-family-code);\n white-space: pre-wrap;\n}\n.dsh-cqa-input:focus-visible,\n.dsh-cqa-textarea:focus-visible {\n outline: 2px solid var(--dsw-alias-state-business-primary);\n outline-offset: 1px;\n}\n.dsh-cqa-input:disabled,\n.dsh-cqa-textarea:disabled {\n opacity: 0.5;\n}\n\n.dsh-cqa-switch {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 0;\n cursor: pointer;\n}\n\n/* ------------------------------------------------------------------------- */\n/* The centralized management overlay */\n/* ------------------------------------------------------------------------- */\n\n/*\n * The overlay and its click-catching backdrop. Neither paints: only DSH alias\n * theme tokens may be used here, and this release has no token to spend on a\n * modal scrim (spec 8.4).\n *\n * These two numbers rank the overlay against its own backdrop, and nothing\n * else. Since ticket 26 the overlay is portaled to the document body, so it and\n * the anchored popovers (19 and 20, still rendered in the input dock) sit in\n * different stacking contexts: which of them paints on top follows from where\n * the dock's own ancestors land in the root context, not from comparing 31\n * against 20. Raising these would not change that.\n */\n.dsh-cqa-manager-backdrop {\n z-index: 30;\n}\n.dsh-cqa-manager {\n position: fixed;\n z-index: 31;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 6px;\n width: min(560px, calc(100vw - 24px));\n max-height: min(80vh, 680px);\n overflow-y: auto;\n padding: 12px;\n border: 0.5px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-specific-tip);\n color: var(--dsw-alias-label-primary);\n box-shadow: var(--dsw-elevation-soft);\n}\n\n.dsh-cqa-manager-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-cqa-manager-title {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.dsh-cqa-section {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 6px 0;\n border-top: 0.5px solid var(--dsw-alias-border-l1);\n}\n.dsh-cqa-section-head {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n.dsh-cqa-section-head .dsh-cqa-section-title {\n flex: 1 1 auto;\n}\n.dsh-cqa-section-title {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n.dsh-cqa-group {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n.dsh-cqa-entry[aria-pressed='true'] {\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n opacity: 1;\n}\n\n.dsh-cqa-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.dsh-cqa-list-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 6px 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n}\n/* A hidden or disabled action stays legible: it is managed here, not removed. */\n.dsh-cqa-list-item[data-quick-action-hidden] .dsh-cqa-list-head,\n.dsh-cqa-list-item[data-quick-action-hidden] .dsh-cqa-list-text {\n opacity: 0.6;\n}\n.dsh-cqa-list-head {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n min-width: 0;\n font-size: 13px;\n line-height: 20px;\n}\n.dsh-cqa-list-text {\n min-width: 0;\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font-family: var(--ds-font-family-code);\n font-size: 11px;\n line-height: 16px;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.dsh-cqa-list-controls {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.dsh-cqa-form {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 6px 0 0;\n border-top: 0.5px solid var(--dsw-alias-border-l1);\n}\n.dsh-cqa-form-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding-top: 6px;\n}\n";
33
+ export declare const QUICK_ACTIONS_CSS = "\n.dsh-cqa-ribbon,\n.dsh-cqa-launcher {\n box-sizing: border-box;\n width: calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance));\n max-width: var(--dsh-composer-card-max-width);\n margin: 0 auto;\n}\n.dsh-cqa-bar {\n box-sizing: border-box;\n min-width: 0;\n max-width: var(--dsh-composer-card-max-width);\n}\n/* Folding: claim the card's width, for the dock row's own max-width to cap. */\n.dsh-cqa-bar[data-quick-actions-overflow] {\n width: var(--dsh-composer-card-max-width);\n}\n\n.dsh-cqa-row {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n padding: 2px 0;\n}\n.dsh-cqa-row[data-density='narrow'] {\n gap: 6px;\n}\n\n.dsh-cqa-title {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n white-space: nowrap;\n}\n\n/* The ribbon overflows horizontally; the management entry never scrolls away. */\n.dsh-cqa-scroll {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: thin;\n}\n.dsh-cqa-fit {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n}\n.dsh-cqa-trailing {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n margin-left: auto;\n}\n\n/*\n * The capsule itself \u2014 height, radius, padding, colours, hover and \":disabled\"\n * \u2014 belongs to the official \"Button\". What is left here is what a shared\n * control cannot know (how it behaves inside these rows) plus what the\n * primitive does not supply. Nothing below may restate a Button property,\n * because the plugin class is applied after the primitive's and would win on\n * equal specificity.\n *\n * The focus ring is one of the things it does not supply: \"Button.module.css\"\n * and \"Pill.module.css\" carry no \":focus\" rule at all \u2014 the library leaves the\n * ring to each component that wants one (\"Input.module.css\" has\n * \":focus-within\", \"HoverCard\" and \"JsonTree\" their own). Spec 8.4 makes a\n * clear focus ring a hard gate, so it stays here for every control this plugin\n * renders.\n */\n.dsh-cqa-action,\n.dsh-cqa-entry {\n /* No global border-box reset exists in this stylesheet, and Button pads\n itself, so the cap has to count that padding to mean 240px on screen. */\n box-sizing: border-box;\n flex: none;\n /* Long labels truncate rather than pushing the row's other controls out. */\n max-width: 240px;\n}\n.dsh-cqa-action:focus-visible,\n.dsh-cqa-entry:focus-visible {\n outline: 2px solid var(--dsw-alias-state-business-primary);\n outline-offset: 1px;\n}\n/* \"aria-disabled\" is not \":disabled\": a control kept focusable while a write is\n in flight still has to read as inert, and no primitive expresses that. */\n.dsh-cqa-entry[aria-disabled='true'] {\n opacity: 0.5;\n cursor: default;\n}\n/* The searchable panel's rows stay native \u2014 a full-width, left-aligned list row\n is not a capsule \u2014 so they still need a focus ring of their own. */\n.dsh-cqa-panel-item:focus-visible,\n.dsh-cqa-link:focus-visible {\n outline: 2px solid var(--dsw-alias-state-business-primary);\n outline-offset: 1px;\n}\n.dsh-cqa-label {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-cqa-icon {\n flex: none;\n}\n/* The chip look is \"Pill\"'s; only its behaviour in a flex row is ours. */\n.dsh-cqa-badge,\n.dsh-cqa-tag {\n flex: none;\n}\n\n.dsh-cqa-note {\n box-sizing: border-box;\n width: 100%;\n margin: 4px 0 0;\n padding: 4px 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-cqa-note-text {\n flex: 1 1 auto;\n min-width: 0;\n}\n.dsh-cqa-link {\n flex: none;\n border: 0;\n background: none;\n padding: 0;\n color: var(--dsw-alias-state-business-primary);\n font: inherit;\n font-size: 12px;\n cursor: pointer;\n text-decoration: underline;\n}\n\n/* Anchored surfaces: the popover list and the confirmation panel. */\n.dsh-cqa-anchor {\n position: relative;\n}\n.dsh-cqa-backdrop {\n position: fixed;\n z-index: 19;\n inset: 0;\n}\n.dsh-cqa-panel {\n position: absolute;\n z-index: 20;\n bottom: calc(100% + 6px);\n left: 0;\n box-sizing: border-box;\n max-width: min(100%, 360px);\n min-width: 220px;\n max-height: 260px;\n overflow-y: auto;\n padding: 6px;\n border: 0.5px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-specific-tip);\n box-shadow: var(--dsw-elevation-soft);\n}\n.dsh-cqa-panel-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-cqa-panel-head .dsh-cqa-panel-title {\n flex: 1 1 auto;\n min-width: 0;\n}\n.dsh-cqa-panel-title {\n padding: 4px 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n.dsh-cqa-panel-item {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 6px 8px;\n border: 0;\n border-radius: 8px;\n background: none;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n text-align: left;\n cursor: pointer;\n}\n.dsh-cqa-panel-item:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-cqa-panel-item:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.dsh-cqa-confirm-text {\n margin: 6px 0;\n padding: 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n font-family: var(--ds-font-family-code);\n font-size: 12px;\n line-height: 18px;\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 160px;\n overflow-y: auto;\n}\n.dsh-cqa-confirm-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n\n/* ------------------------------------------------------------------------- */\n/* Fields, shared by the search box and the Custom Quick Action form */\n/* ------------------------------------------------------------------------- */\n\n.dsh-cqa-field {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 4px 0;\n}\n.dsh-cqa-field-label {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n}\n.dsh-cqa-field-hint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n.dsh-cqa-field-error {\n color: var(--dsw-alias-state-danger-primary, var(--dsw-alias-label-primary));\n font-size: 11px;\n line-height: 16px;\n font-weight: 500;\n}\n\n.dsh-cqa-input,\n.dsh-cqa-textarea {\n box-sizing: border-box;\n width: 100%;\n padding: 4px 8px;\n border: 0.5px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n}\n.dsh-cqa-textarea {\n resize: vertical;\n min-height: 72px;\n font-family: var(--ds-font-family-code);\n white-space: pre-wrap;\n}\n.dsh-cqa-input:focus-visible,\n.dsh-cqa-textarea:focus-visible {\n outline: 2px solid var(--dsw-alias-state-business-primary);\n outline-offset: 1px;\n}\n.dsh-cqa-input:disabled,\n.dsh-cqa-textarea:disabled {\n opacity: 0.5;\n}\n\n.dsh-cqa-switch {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 0;\n cursor: pointer;\n}\n\n/* ------------------------------------------------------------------------- */\n/* The centralized management overlay */\n/* ------------------------------------------------------------------------- */\n\n/*\n * The overlay and its click-catching backdrop. Neither paints: only DSH alias\n * theme tokens may be used here, and this release has no token to spend on a\n * modal scrim (spec 8.4).\n *\n * These two numbers rank the overlay against its own backdrop, and nothing\n * else. Since ticket 26 the overlay is portaled to the document body, so it and\n * the anchored popovers (19 and 20, still rendered in the input dock) sit in\n * different stacking contexts: which of them paints on top follows from where\n * the dock's own ancestors land in the root context, not from comparing 31\n * against 20. Raising these would not change that.\n */\n.dsh-cqa-manager-backdrop {\n z-index: 30;\n}\n.dsh-cqa-manager {\n position: fixed;\n z-index: 31;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 6px;\n width: min(560px, calc(100vw - 24px));\n max-height: min(80vh, 680px);\n overflow-y: auto;\n padding: 12px;\n border: 0.5px solid var(--dsw-alias-border-l1);\n border-radius: 12px;\n background: var(--dsw-specific-tip);\n color: var(--dsw-alias-label-primary);\n box-shadow: var(--dsw-elevation-soft);\n}\n\n.dsh-cqa-manager-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-cqa-manager-title {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.dsh-cqa-section {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 6px 0;\n border-top: 0.5px solid var(--dsw-alias-border-l1);\n}\n.dsh-cqa-section-head {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n.dsh-cqa-section-head .dsh-cqa-section-title {\n flex: 1 1 auto;\n}\n.dsh-cqa-section-title {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n.dsh-cqa-group {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n.dsh-cqa-entry[aria-pressed='true'] {\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n opacity: 1;\n}\n\n.dsh-cqa-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.dsh-cqa-list-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 6px 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n}\n/* A hidden or disabled action stays legible: it is managed here, not removed. */\n.dsh-cqa-list-item[data-quick-action-hidden] .dsh-cqa-list-head,\n.dsh-cqa-list-item[data-quick-action-hidden] .dsh-cqa-list-text {\n opacity: 0.6;\n}\n.dsh-cqa-list-head {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n min-width: 0;\n font-size: 13px;\n line-height: 20px;\n}\n.dsh-cqa-list-text {\n min-width: 0;\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font-family: var(--ds-font-family-code);\n font-size: 11px;\n line-height: 16px;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.dsh-cqa-list-controls {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.dsh-cqa-form {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 6px 0 0;\n border-top: 0.5px solid var(--dsw-alias-border-l1);\n}\n.dsh-cqa-form-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding-top: 6px;\n}\n";
30
34
  /**
31
35
  * Install the stylesheet once per document and return its disposer, so the
32
36
  * Client fiber owns it like every other registration (spec 7.3).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-quick-actions",
3
- "version": "0.1.0",
3
+ "version": "0.2.0-rc.2",
4
4
  "description": "Persistent Quick Actions for the DSH message composer",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -60,23 +60,28 @@
60
60
  }
61
61
  },
62
62
  "peerDependencies": {
63
- "@deepseek-ai/cordis": "^4.0.2",
64
- "@deepseek-ai/dsh-client-connection": ">=0.1.5-rc.1",
65
- "@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1",
66
- "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1",
67
- "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.5-rc.1",
68
- "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.1",
69
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.1",
70
- "@deepseek-ai/dsh-settings": ">=0.1.5-rc.1",
71
- "@deepseek-ai/schemastery": "^3.18.2",
63
+ "@deepseek-ai/cordis": "^4.0.4",
64
+ "@deepseek-ai/dsh-client-connection": ">=0.1.7-alpha.2",
65
+ "@deepseek-ai/dsh-client-locale": ">=0.1.7-alpha.2",
66
+ "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.7-alpha.2",
67
+ "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.7-alpha.2",
68
+ "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.7-alpha.2",
69
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-alpha.2",
70
+ "@deepseek-ai/dsh-settings": ">=0.1.7-alpha.2",
71
+ "@deepseek-ai/schemastery": "^3.18.4",
72
72
  "react": "^18.3.1",
73
73
  "react-dom": "^18.3.1"
74
74
  },
75
75
  "devDependencies": {
76
- "@deepseek-ai/cordis": "^4.0.2",
76
+ "@deepseek-ai/cordis": "^4.0.4",
77
+ "@deepseek-ai/dsh-client-connection": "0.1.7-rc.1",
78
+ "@deepseek-ai/dsh-client-locale": "0.1.7-rc.1",
79
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.1",
77
80
  "@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
78
- "@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
79
- "@deepseek-ai/schemastery": "^3.18.2",
81
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.1",
82
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.1",
83
+ "@deepseek-ai/dsh-settings": "0.1.7-rc.1",
84
+ "@deepseek-ai/schemastery": "^3.18.4",
80
85
  "@types/react": "~18.3.31",
81
86
  "@types/react-dom": "~18.3.7",
82
87
  "react": "^18.3.1",