dsh-quick-actions 0.2.0-rc.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -144,9 +144,11 @@ export interface SessionSlotProps {
144
144
  export type InputDockProps = SessionSlotProps & InputZoneOwnerProps;
145
145
  /** Props of the `conversation.composer.dock` entry (this Slot declares no owner props). */
146
146
  export type ComposerDockProps = SessionSlotProps;
147
- /** Registration options both dock Slots accept. */
147
+ /** Props of the optional local core footer Slot (session scope, no owner props). */
148
+ export type ComposerFooterProps = SessionSlotProps;
149
+ /** Registration options the dock and optional footer Slots accept. */
148
150
  export interface SlotRegisterOptions {
149
- readonly name: 'conversation.input.dock' | 'conversation.composer.dock';
151
+ readonly name: 'conversation.input.dock' | 'conversation.composer.dock' | 'conversation.composer.footer';
150
152
  /** Cell key; a fresh id is added beside the shipped entries. */
151
153
  readonly id: string;
152
154
  /** Position among the entries, ascending. */
@@ -4,7 +4,7 @@
4
4
  * This fiber owns everything the feature holds in the browser: one global
5
5
  * `QuickActionsController` over the entry's Settings form, the per-Session
6
6
  * execution registry, the Resident Composer registry, the locale dictionaries,
7
- * the stylesheet, and the two dock Slot registrations. All of it is installed
7
+ * the stylesheet, and the dock/optional footer Slot registrations. All of it is installed
8
8
  * through `ctx.effect` and `ctx.slots.inject`, so unloading the plugin leaves
9
9
  * no listener, registration, namespace, style tag or subscription behind
10
10
  * (spec 7.3).
@@ -2,7 +2,7 @@ import type { ReactElement } from 'react';
2
2
  import type { ResidentComposerRegistry } from './residency.js';
3
3
  import type { QuickActionSessionRegistry } from '../session/execution.js';
4
4
  import type { QuickActionsController } from '../controller.js';
5
- import type { ComposerBlocks, ComposerDockProps, InputDockProps } from '../dsh.js';
5
+ import type { ComposerBlocks, ComposerDockProps, ComposerFooterProps, InputDockProps } from '../dsh.js';
6
6
  /** Everything the Slot entries reach outside React. */
7
7
  export interface QuickActionSurfaceDeps {
8
8
  readonly controller: QuickActionsController;
@@ -23,5 +23,6 @@ export interface QuickActionSurfaceDeps {
23
23
  export declare function createQuickActionDockEntries(deps: QuickActionSurfaceDeps): {
24
24
  readonly InputDock: (props: InputDockProps) => ReactElement;
25
25
  readonly ComposerDock: (props: ComposerDockProps) => ReactElement;
26
+ readonly FooterDock: (props: ComposerFooterProps) => ReactElement;
26
27
  readonly ManagerDock: (props: InputDockProps) => ReactElement;
27
28
  };
@@ -20,7 +20,11 @@
20
20
  * — the same cap the composer card uses — and is centred, so its left and right
21
21
  * edges coincide with the input box exactly rather than approximately.
22
22
  *
23
- * `.dsh-cqa-bar` makes no such claim. Since DSH 0.1.6-alpha.2 the composer dock is
23
+ * In the optional composer footer, the core owns card alignment and the bar
24
+ * fills that row; its control group is centred (spec 23.1). The rules below
25
+ * still apply to the fallback for unpatched cores.
26
+ *
27
+ * `.dsh-cqa-bar` in that fallback makes no such claim. Since DSH 0.1.6-alpha.2 the composer dock is
24
28
  * a row under the card that DSH centres and sizes to its content, shared with
25
29
  * DSH's own stats pills and context meter, so the bar is a content-sized member of
26
30
  * that row (spec 22.9). It only has to stay inside it: `min-width: 0` lets it
@@ -30,7 +34,7 @@
30
34
  * `max-width: 100%`: content-sized, the region the split measures would only be
31
35
  * as wide as what it already shows, and a wider window could never unfold it.
32
36
  */
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";
37
+ 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/* The optional footer is already aligned to the card by its core owner.\n Only this plugin's row shrinks and centres the whole control group. */\n.dsh-cqa-footer {\n width: 100%;\n min-width: 0;\n}\n.dsh-cqa-footer > .dsh-cqa-bar {\n width: 100%;\n}\n.dsh-cqa-footer .dsh-cqa-row {\n width: fit-content;\n max-width: 100%;\n margin-inline: auto;\n}\n.dsh-cqa-footer [data-quick-actions-overflow] .dsh-cqa-row {\n width: 100%;\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";
34
38
  /**
35
39
  * Install the stylesheet once per document and return its disposer, so the
36
40
  * 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.2.0-rc.2",
3
+ "version": "0.2.0",
4
4
  "description": "Persistent Quick Actions for the DSH message composer",
5
5
  "license": "MIT",
6
6
  "repository": {