@kubex/zinc 1.1.80 → 1.1.82

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.
package/dist/zn.d.ts CHANGED
@@ -1857,9 +1857,292 @@ declare module "components/data-table-filter/index" {
1857
1857
  }
1858
1858
  }
1859
1859
  }
1860
+ declare module "components/slash-menu/slash-menu-items" {
1861
+ export interface SlashMenuItem {
1862
+ /** The text shown in the menu. */
1863
+ label: string;
1864
+ /** The text inserted into the field. Omit for items handled entirely by the `zn-slash-select` event. */
1865
+ value?: string;
1866
+ /** Icon shown against the item, e.g. `tag@lu`. */
1867
+ icon?: string;
1868
+ /** Supporting text shown under the label. */
1869
+ description?: string;
1870
+ /** Extra terms the item can be found by. */
1871
+ keywords?: string | string[];
1872
+ /** Heading the item is listed under. Items without a group are listed first, in source order. */
1873
+ group?: string;
1874
+ /** Overrides the position of the item within its match band. Lower sorts first. */
1875
+ order?: number;
1876
+ /** Identifier passed through on `zn-slash-select`, for items that do something other than insert text. */
1877
+ action?: string;
1878
+ /** Where the caret lands after insertion, as an offset into `value`. Defaults to the end. */
1879
+ caretOffset?: number;
1880
+ /** Listed, but not selectable. */
1881
+ disabled?: boolean;
1882
+ }
1883
+ /**
1884
+ * Registers a named, reusable set of insertions, so a list defined once (e.g. the merge fields
1885
+ * allowed in legal copy) can be referenced from markup with `slash-preset="<name>"`.
1886
+ */
1887
+ export function registerSlashMenuPreset(name: string, items: SlashMenuItem[]): void;
1888
+ /** Removes a preset registered with `registerSlashMenuPreset`. */
1889
+ export function unregisterSlashMenuPreset(name: string): void;
1890
+ /** The names of every registered preset. */
1891
+ export function slashMenuPresetNames(): string[];
1892
+ /** Resolves one or more preset names (comma separated, or an array) to their items. */
1893
+ export function getSlashMenuPreset(names: string | string[]): SlashMenuItem[];
1894
+ /**
1895
+ * Parses the `slash-items` attribute. Accepts a JSON array of items, or the shorthand
1896
+ * `Label={{TOKEN}}, Other={{OTHER}}` (the label may be omitted to use the token as its own label).
1897
+ */
1898
+ export function parseSlashItems(value: string | null | undefined): SlashMenuItem[];
1899
+ /** Filters and ranks items against a query. An empty query keeps every item in its declared order. */
1900
+ export function filterSlashItems(items: SlashMenuItem[], query: string): SlashMenuItem[];
1901
+ }
1902
+ declare module "utilities/caret-position" {
1903
+ export interface CaretCoordinates {
1904
+ top: number;
1905
+ left: number;
1906
+ height: number;
1907
+ }
1908
+ export type TextField = HTMLTextAreaElement | HTMLInputElement;
1909
+ /**
1910
+ * Measures where the caret sits inside a text field, relative to the field's own top/left corner.
1911
+ * There is no browser API for this, so the field is mirrored into an off-screen div and the offset
1912
+ * of a marker span at `index` is read back.
1913
+ */
1914
+ export function getCaretCoordinates(field: TextField, index: number): CaretCoordinates;
1915
+ /**
1916
+ * Projects measured caret coordinates onto the viewport, clamped to the field's box so a caret
1917
+ * scrolled out of view doesn't drag anchored content off with it. Split from the measurement so a
1918
+ * cached measurement can be re-projected as the field scrolls or moves.
1919
+ */
1920
+ export function caretRectFrom(field: TextField, { top, left, height }: CaretCoordinates): DOMRect;
1921
+ /** The caret's position as a viewport rect. */
1922
+ export function getCaretRect(field: TextField, index: number): DOMRect;
1923
+ }
1924
+ declare module "components/slash-menu/slash-menu.component" {
1925
+ import ZincElement from "internal/zinc-element";
1926
+ import ZnIcon from "components/icon/index";
1927
+ import type { CSSResultGroup, PropertyValues } from 'lit';
1928
+ import type { Placement, VirtualElement } from '@floating-ui/dom';
1929
+ import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
1930
+ export const SLASH_ITEM_SELECT = "zn-slash-item-select";
1931
+ /**
1932
+ * @summary A keyboard-driven list of insertions, anchored to the caret of the field that opened it.
1933
+ * @documentation https://zinc.style/components/slash-menu
1934
+ * @status experimental
1935
+ * @since 1.1
1936
+ *
1937
+ * @dependency zn-icon
1938
+ *
1939
+ * @event zn-slash-item-select - Emitted when an item is chosen. Does not cross shadow boundaries; the
1940
+ * component driving the menu (e.g. `zn-textarea`) re-emits it as `zn-slash-select`.
1941
+ *
1942
+ * @csspart panel - The floating panel that holds the list.
1943
+ * @csspart heading - The panel's heading.
1944
+ * @csspart item - An item in the list.
1945
+ * @csspart group-heading - A group heading between items.
1946
+ * @csspart footer - The truncation footer, shown when not every match fits.
1947
+ *
1948
+ * @cssproperty --slash-menu-width - The width of the panel.
1949
+ * @cssproperty --slash-menu-max-height - The maximum height of the panel before it scrolls.
1950
+ */
1951
+ export default class ZnSlashMenu extends ZincElement {
1952
+ static styles: CSSResultGroup;
1953
+ static dependencies: {
1954
+ 'zn-icon': typeof ZnIcon;
1955
+ };
1956
+ private panel;
1957
+ private stopAutoUpdate?;
1958
+ /** Whether the menu is showing. */
1959
+ open: boolean;
1960
+ /** The items to list. Already filtered — the menu displays what it is given. */
1961
+ items: SlashMenuItem[];
1962
+ /** The query the items were matched against, shown in the heading. */
1963
+ query: string;
1964
+ /** The heading shown when there is no query. */
1965
+ heading: string;
1966
+ /** Shown in place of the list when there are no items. */
1967
+ emptyText: string;
1968
+ /** The most items to render at once. Remaining matches are reported in the footer. */
1969
+ maxItems: number;
1970
+ /** The element or caret rect the panel is positioned against. */
1971
+ anchor: Element | VirtualElement | null;
1972
+ /** The preferred placement of the panel. */
1973
+ placement: Placement;
1974
+ /** The gap between the caret and the panel. */
1975
+ distance: number;
1976
+ private activeIndex;
1977
+ private get visibleItems();
1978
+ /** The item that Enter would insert. */
1979
+ get activeItem(): SlashMenuItem | undefined;
1980
+ show(): void;
1981
+ hide(): void;
1982
+ /** Sets the active item by index, wrapping at both ends and skipping disabled items. */
1983
+ setActiveIndex(index: number): void;
1984
+ /** Moves the active item by `delta` places. */
1985
+ moveActive(delta: number): void;
1986
+ /** Chooses the active item, as pressing Enter would. */
1987
+ selectActive(): void;
1988
+ /** Recalculates the panel's position against its anchor. */
1989
+ reposition(): void;
1990
+ connectedCallback(): void;
1991
+ disconnectedCallback(): void;
1992
+ private startPositioner;
1993
+ private stopPositioner;
1994
+ private position;
1995
+ private selectItem;
1996
+ private scrollActiveIntoView;
1997
+ private readonly handleItemMouseDown;
1998
+ protected willUpdate(changed: PropertyValues): void;
1999
+ protected updated(changed: PropertyValues): void;
2000
+ private renderItem;
2001
+ private renderItems;
2002
+ render(): import("lit-html").TemplateResult<1>;
2003
+ }
2004
+ }
2005
+ declare module "components/slash-menu/slash-menu-controller" {
2006
+ import type { TextField } from "utilities/caret-position";
2007
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2008
+ import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
2009
+ import type ZnSlashMenu from "components/slash-menu/slash-menu.component";
2010
+ export interface SlashMenuControllerOptions {
2011
+ /**
2012
+ * Resolves the menu to render results into. Called the first time the menu is needed, so the host
2013
+ * can render it lazily; may return a promise (e.g. after awaiting `updateComplete`).
2014
+ */
2015
+ menu: () => ZnSlashMenu | null | Promise<ZnSlashMenu | null>;
2016
+ /** The available items, unfiltered. Receives the current query so lists can be resolved remotely. */
2017
+ items: (query: string) => SlashMenuItem[] | Promise<SlashMenuItem[]>;
2018
+ /** The characters that open the menu. Defaults to `/`. */
2019
+ trigger?: () => string;
2020
+ /** Called before an item is inserted. Return `false` to handle the item yourself. */
2021
+ onSelect?: (item: SlashMenuItem, query: string) => boolean;
2022
+ /** Called after an item's value has been written into the field. */
2023
+ onInsert?: (item: SlashMenuItem, value: string) => void;
2024
+ }
2025
+ /**
2026
+ * Drives a slash menu for a plain `<textarea>` or `<input>`: watches the caret for the trigger
2027
+ * sequence, resolves and filters items, and inserts the chosen value.
2028
+ *
2029
+ * The host owns the field and the menu element; this controller owns the interaction.
2030
+ */
2031
+ export class SlashMenuController implements ReactiveController {
2032
+ private readonly host;
2033
+ private readonly options;
2034
+ private readonly caretAnchor;
2035
+ private field;
2036
+ private menu;
2037
+ private triggerIndex;
2038
+ private query;
2039
+ /** Trigger position the user dismissed with Escape; the menu stays shut until they move off it. */
2040
+ private dismissedIndex;
2041
+ private resolveToken;
2042
+ private inserting;
2043
+ private isOpen;
2044
+ private listening;
2045
+ /** Caret measurement is the expensive part of positioning, so the last one is reused. */
2046
+ private measured?;
2047
+ constructor(host: ReactiveControllerHost & HTMLElement, options: SlashMenuControllerOptions);
2048
+ /** Whether the menu is currently showing. */
2049
+ get open(): boolean;
2050
+ hostConnected(): void;
2051
+ hostDisconnected(): void;
2052
+ /** Starts watching a field. Safe to call repeatedly with the same field. */
2053
+ attach(field: TextField): void;
2054
+ /** Stops watching the current field and closes the menu. */
2055
+ detach(): void;
2056
+ private addListeners;
2057
+ private removeListeners;
2058
+ /** Closes the menu without marking the trigger as dismissed. */
2059
+ close(): void;
2060
+ /** Opens the menu at the caret, as a toolbar button or keyboard shortcut would. */
2061
+ requestOpen(): void;
2062
+ private caretRect;
2063
+ private readonly handleInput;
2064
+ private readonly handleCaretMove;
2065
+ private readonly handleKeyUp;
2066
+ private readonly handleBlur;
2067
+ private readonly handleScroll;
2068
+ private readonly handleKeyDown;
2069
+ private readonly handleItemSelect;
2070
+ private detect;
2071
+ private resolve;
2072
+ private select;
2073
+ private replace;
2074
+ }
2075
+ }
2076
+ declare module "components/slash-item/slash-item.component" {
2077
+ import ZincElement from "internal/zinc-element";
2078
+ import type { CSSResultGroup } from 'lit';
2079
+ import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
2080
+ /**
2081
+ * @summary Declares a single insertion for a slash menu. Renders nothing itself — it describes an
2082
+ * entry for the component it is slotted into, e.g. `<zn-textarea>`'s `slash-items` slot.
2083
+ * @documentation https://zinc.style/components/slash-item
2084
+ * @status experimental
2085
+ * @since 1.1
2086
+ *
2087
+ * @slot - The text to insert, for values that are long or span multiple lines. Ignored when the
2088
+ * `value` attribute is set.
2089
+ */
2090
+ export default class ZnSlashItem extends ZincElement {
2091
+ static styles: CSSResultGroup;
2092
+ /** The text shown in the menu. */
2093
+ label: string;
2094
+ /** The text inserted into the field. Falls back to this element's text content. */
2095
+ value: string;
2096
+ /** Icon shown against the item, e.g. `tag@lu`. */
2097
+ icon: string;
2098
+ /** Supporting text shown under the label. */
2099
+ description: string;
2100
+ /** Extra terms the item can be found by, comma separated. */
2101
+ keywords: string;
2102
+ /** Heading the item is listed under. */
2103
+ group: string;
2104
+ /** Overrides the item's position in the menu. Lower sorts first. */
2105
+ order: number;
2106
+ /** Where the caret lands after insertion, as an offset into the inserted value. */
2107
+ caretOffset: number;
2108
+ /** Identifier passed through on `zn-slash-select`, for items that do something other than insert. */
2109
+ action: string;
2110
+ /** Listed, but not selectable. */
2111
+ disabled: boolean;
2112
+ /** The item as the slash menu consumes it. */
2113
+ toSlashMenuItem(): SlashMenuItem;
2114
+ private get insertValue();
2115
+ render(): import("lit-html").TemplateResult<1>;
2116
+ }
2117
+ }
2118
+ declare module "components/slash-item/index" {
2119
+ import ZnSlashItem from "components/slash-item/slash-item.component";
2120
+ export * from "components/slash-item/slash-item.component";
2121
+ export default ZnSlashItem;
2122
+ global {
2123
+ interface HTMLElementTagNameMap {
2124
+ 'zn-slash-item': ZnSlashItem;
2125
+ }
2126
+ }
2127
+ }
2128
+ declare module "components/slash-menu/index" {
2129
+ import ZnSlashMenu from "components/slash-menu/slash-menu.component";
2130
+ export * from "components/slash-menu/slash-menu.component";
2131
+ export * from "components/slash-menu/slash-menu-controller";
2132
+ export * from "components/slash-menu/slash-menu-items";
2133
+ export default ZnSlashMenu;
2134
+ global {
2135
+ interface HTMLElementTagNameMap {
2136
+ 'zn-slash-menu': ZnSlashMenu;
2137
+ }
2138
+ }
2139
+ }
1860
2140
  declare module "components/input/input.component" {
2141
+ import { type SlashMenuItem } from "components/slash-menu/slash-menu-items";
1861
2142
  import ZincElement from "internal/zinc-element";
1862
2143
  import ZnIcon from "components/icon/index";
2144
+ import ZnSlashItem from "components/slash-item/index";
2145
+ import ZnSlashMenu from "components/slash-menu/index";
1863
2146
  import ZnTooltip from "components/tooltip/index";
1864
2147
  import type { ZincFormControl } from "internal/zinc-element";
1865
2148
  /**
@@ -1887,8 +2170,20 @@ declare module "components/input/input.component" {
1887
2170
  * @slot show-password-icon - An icon to use in lieu of the default show password icon.
1888
2171
  * @slot hide-password-icon - An icon to use in lieu of the default hide password icon.
1889
2172
  * @slot help-text - Text that describes how to use the input. Alternatively, you can use the `help-text` attribute.
2173
+ * @slot slash-items - `<zn-slash-item>` elements describing the insertions offered by the slash menu. Items are
2174
+ * picked up wherever they sit inside the input, so this slot name is optional.
2175
+ * @slot slash-menu - A `<zn-slash-menu>` to use instead of the built-in one, so its heading, sizing and styling can
2176
+ * be set in markup. Any `<zn-slash-item>` children of it become the menu's items.
2177
+ *
2178
+ * @dependency zn-slash-item
2179
+ * @dependency zn-slash-menu
2180
+ *
2181
+ * @event zn-slash-select - Emitted when a slash menu item is chosen. Cancelable — call `preventDefault()` to
2182
+ * suppress the insertion and handle the item yourself.
2183
+ * @event zn-slash-insert - Emitted after a slash menu item's value has been inserted.
1890
2184
  *
1891
2185
  * @csspart form-control - The form control that wraps the label, input, and help text.
2186
+ * @csspart slash-menu - The slash menu shown at the caret.
1892
2187
  * @csspart form-control-label - The label's wrapper.
1893
2188
  * @csspart form-control-input - The input's wrapper.
1894
2189
  * @csspart form-control-help-text - The help text's wrapper.
@@ -1909,14 +2204,20 @@ declare module "components/input/input.component" {
1909
2204
  static styles: import("lit").CSSResult;
1910
2205
  static dependencies: {
1911
2206
  'zn-icon': typeof ZnIcon;
2207
+ 'zn-slash-item': typeof ZnSlashItem;
2208
+ 'zn-slash-menu': typeof ZnSlashMenu;
1912
2209
  'zn-tooltip': typeof ZnTooltip;
1913
2210
  };
1914
2211
  private readonly formControlController;
1915
2212
  private readonly hasSlotController;
1916
2213
  private readonly localize;
2214
+ private readonly slashController;
1917
2215
  input: HTMLInputElement;
1918
2216
  colorPicker: HTMLInputElement;
2217
+ slashMenuElement: ZnSlashMenu | null;
1919
2218
  private hasFocus;
2219
+ /** Renders the slash menu only once it has been needed, keeping unused inputs cheap. */
2220
+ private hasSlashMenu;
1920
2221
  private isUserTyping;
1921
2222
  title: string;
1922
2223
  private __numberInput;
@@ -2019,6 +2320,23 @@ declare module "components/input/input.component" {
2019
2320
  * keyboard on supportive devices.
2020
2321
  */
2021
2322
  inputmode: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';
2323
+ /**
2324
+ * Quick insertions offered by the slash menu. Accepts a JSON array of items, or the shorthand
2325
+ * `Brand name={{BRAND_NAME}}, Support email={{SUPPORT_EMAIL}}`. Can also be set as an array of
2326
+ * `SlashMenuItem` objects in JavaScript.
2327
+ */
2328
+ slashItems: SlashMenuItem[];
2329
+ /** Names of item sets registered with `registerSlashMenuPreset`, comma separated. */
2330
+ slashPreset: string;
2331
+ /** The characters that open the slash menu. */
2332
+ slashTrigger: string;
2333
+ /** The heading shown above the slash menu's items. */
2334
+ slashHeading: string;
2335
+ /**
2336
+ * Resolves additional items each time the menu opens, for lists that come from elsewhere (e.g. an
2337
+ * API). Receives the current query and may return a promise. JavaScript only.
2338
+ */
2339
+ slashItemsProvider?: (query: string) => SlashMenuItem[] | Promise<SlashMenuItem[]>;
2022
2340
  /**
2023
2341
  * When enabled, pressing enter will always submit the surrounding form, even when the form uses
2024
2342
  * enter-navigation to move between fields.
@@ -2058,6 +2376,14 @@ declare module "components/input/input.component" {
2058
2376
  private handleColorPickerChange;
2059
2377
  private focusInput;
2060
2378
  protected firstUpdated(): void;
2379
+ /** The insertions the slash menu offers, gathered from every source, in the order they were declared. */
2380
+ resolveSlashItems(search?: string): Promise<SlashMenuItem[]>;
2381
+ /** Opens the slash menu at the caret, inserting the trigger if it isn't already there. */
2382
+ showSlashMenu(): Promise<void>;
2383
+ /** Closes the slash menu. */
2384
+ hideSlashMenu(): void;
2385
+ private slottedSlashItems;
2386
+ private mountSlashMenu;
2061
2387
  handleDisabledChange(): void;
2062
2388
  handleStepChange(): void;
2063
2389
  handleValueChange(): Promise<void>;
@@ -4809,51 +5135,9 @@ declare module "components/icon-picker/index" {
4809
5135
  export default ZnIconPicker;
4810
5136
  global {
4811
5137
  interface HTMLElementTagNameMap {
4812
- 'zn-icon-picker': ZnIconPicker;
4813
- }
4814
- }
4815
- }
4816
- declare module "components/slash-menu/slash-menu-items" {
4817
- export interface SlashMenuItem {
4818
- /** The text shown in the menu. */
4819
- label: string;
4820
- /** The text inserted into the field. Omit for items handled entirely by the `zn-slash-select` event. */
4821
- value?: string;
4822
- /** Icon shown against the item, e.g. `tag@lu`. */
4823
- icon?: string;
4824
- /** Supporting text shown under the label. */
4825
- description?: string;
4826
- /** Extra terms the item can be found by. */
4827
- keywords?: string | string[];
4828
- /** Heading the item is listed under. Items without a group are listed first, in source order. */
4829
- group?: string;
4830
- /** Overrides the position of the item within its match band. Lower sorts first. */
4831
- order?: number;
4832
- /** Identifier passed through on `zn-slash-select`, for items that do something other than insert text. */
4833
- action?: string;
4834
- /** Where the caret lands after insertion, as an offset into `value`. Defaults to the end. */
4835
- caretOffset?: number;
4836
- /** Listed, but not selectable. */
4837
- disabled?: boolean;
4838
- }
4839
- /**
4840
- * Registers a named, reusable set of insertions, so a list defined once (e.g. the merge fields
4841
- * allowed in legal copy) can be referenced from markup with `slash-preset="<name>"`.
4842
- */
4843
- export function registerSlashMenuPreset(name: string, items: SlashMenuItem[]): void;
4844
- /** Removes a preset registered with `registerSlashMenuPreset`. */
4845
- export function unregisterSlashMenuPreset(name: string): void;
4846
- /** The names of every registered preset. */
4847
- export function slashMenuPresetNames(): string[];
4848
- /** Resolves one or more preset names (comma separated, or an array) to their items. */
4849
- export function getSlashMenuPreset(names: string | string[]): SlashMenuItem[];
4850
- /**
4851
- * Parses the `slash-items` attribute. Accepts a JSON array of items, or the shorthand
4852
- * `Label={{TOKEN}}, Other={{OTHER}}` (the label may be omitted to use the token as its own label).
4853
- */
4854
- export function parseSlashItems(value: string | null | undefined): SlashMenuItem[];
4855
- /** Filters and ranks items against a query. An empty query keeps every item in its declared order. */
4856
- export function filterSlashItems(items: SlashMenuItem[], query: string): SlashMenuItem[];
5138
+ 'zn-icon-picker': ZnIconPicker;
5139
+ }
5140
+ }
4857
5141
  }
4858
5142
  declare module "components/inline-edit/inline-edit.component" {
4859
5143
  import { type CSSResultGroup, type HTMLTemplateResult, type PropertyValues } from 'lit';
@@ -4914,8 +5198,8 @@ declare module "components/inline-edit/inline-edit.component" {
4914
5198
  inputType: 'select' | 'text' | 'data-select' | 'number' | 'textarea';
4915
5199
  textareaRows: 1;
4916
5200
  /**
4917
- * Quick insertions offered by the slash menu of a `textarea` input. Accepts a JSON array of items, or the
4918
- * shorthand `Brand name={{BRAND_NAME}}, Support email={{SUPPORT_EMAIL}}`. Forwarded to the inner `zn-textarea`.
5201
+ * Quick insertions offered by the slash menu of a `text` or `textarea` input. Accepts a JSON array of items, or
5202
+ * the shorthand `Brand name={{BRAND_NAME}}, Support email={{SUPPORT_EMAIL}}`.
4919
5203
  */
4920
5204
  slashItems: SlashMenuItem[];
4921
5205
  /** Names of item sets registered with `registerSlashMenuPreset`, comma separated. */
@@ -6262,244 +6546,6 @@ declare module "components/editor/modules/ai/tooltip/ai-tooltip.component" {
6262
6546
  render(): import("lit-html").TemplateResult<1>;
6263
6547
  }
6264
6548
  }
6265
- declare module "utilities/caret-position" {
6266
- export interface CaretCoordinates {
6267
- top: number;
6268
- left: number;
6269
- height: number;
6270
- }
6271
- export type TextField = HTMLTextAreaElement | HTMLInputElement;
6272
- /**
6273
- * Measures where the caret sits inside a text field, relative to the field's own top/left corner.
6274
- * There is no browser API for this, so the field is mirrored into an off-screen div and the offset
6275
- * of a marker span at `index` is read back.
6276
- */
6277
- export function getCaretCoordinates(field: TextField, index: number): CaretCoordinates;
6278
- /**
6279
- * Projects measured caret coordinates onto the viewport, clamped to the field's box so a caret
6280
- * scrolled out of view doesn't drag anchored content off with it. Split from the measurement so a
6281
- * cached measurement can be re-projected as the field scrolls or moves.
6282
- */
6283
- export function caretRectFrom(field: TextField, { top, left, height }: CaretCoordinates): DOMRect;
6284
- /** The caret's position as a viewport rect. */
6285
- export function getCaretRect(field: TextField, index: number): DOMRect;
6286
- }
6287
- declare module "components/slash-menu/slash-menu.component" {
6288
- import ZincElement from "internal/zinc-element";
6289
- import ZnIcon from "components/icon/index";
6290
- import type { CSSResultGroup, PropertyValues } from 'lit';
6291
- import type { Placement, VirtualElement } from '@floating-ui/dom';
6292
- import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
6293
- export const SLASH_ITEM_SELECT = "zn-slash-item-select";
6294
- /**
6295
- * @summary A keyboard-driven list of insertions, anchored to the caret of the field that opened it.
6296
- * @documentation https://zinc.style/components/slash-menu
6297
- * @status experimental
6298
- * @since 1.1
6299
- *
6300
- * @dependency zn-icon
6301
- *
6302
- * @event zn-slash-item-select - Emitted when an item is chosen. Does not cross shadow boundaries; the
6303
- * component driving the menu (e.g. `zn-textarea`) re-emits it as `zn-slash-select`.
6304
- *
6305
- * @csspart panel - The floating panel that holds the list.
6306
- * @csspart heading - The panel's heading.
6307
- * @csspart item - An item in the list.
6308
- * @csspart group-heading - A group heading between items.
6309
- * @csspart footer - The truncation footer, shown when not every match fits.
6310
- *
6311
- * @cssproperty --slash-menu-width - The width of the panel.
6312
- * @cssproperty --slash-menu-max-height - The maximum height of the panel before it scrolls.
6313
- */
6314
- export default class ZnSlashMenu extends ZincElement {
6315
- static styles: CSSResultGroup;
6316
- static dependencies: {
6317
- 'zn-icon': typeof ZnIcon;
6318
- };
6319
- private panel;
6320
- private stopAutoUpdate?;
6321
- /** Whether the menu is showing. */
6322
- open: boolean;
6323
- /** The items to list. Already filtered — the menu displays what it is given. */
6324
- items: SlashMenuItem[];
6325
- /** The query the items were matched against, shown in the heading. */
6326
- query: string;
6327
- /** The heading shown when there is no query. */
6328
- heading: string;
6329
- /** Shown in place of the list when there are no items. */
6330
- emptyText: string;
6331
- /** The most items to render at once. Remaining matches are reported in the footer. */
6332
- maxItems: number;
6333
- /** The element or caret rect the panel is positioned against. */
6334
- anchor: Element | VirtualElement | null;
6335
- /** The preferred placement of the panel. */
6336
- placement: Placement;
6337
- /** The gap between the caret and the panel. */
6338
- distance: number;
6339
- private activeIndex;
6340
- private get visibleItems();
6341
- /** The item that Enter would insert. */
6342
- get activeItem(): SlashMenuItem | undefined;
6343
- show(): void;
6344
- hide(): void;
6345
- /** Sets the active item by index, wrapping at both ends and skipping disabled items. */
6346
- setActiveIndex(index: number): void;
6347
- /** Moves the active item by `delta` places. */
6348
- moveActive(delta: number): void;
6349
- /** Chooses the active item, as pressing Enter would. */
6350
- selectActive(): void;
6351
- /** Recalculates the panel's position against its anchor. */
6352
- reposition(): void;
6353
- connectedCallback(): void;
6354
- disconnectedCallback(): void;
6355
- private startPositioner;
6356
- private stopPositioner;
6357
- private position;
6358
- private selectItem;
6359
- private scrollActiveIntoView;
6360
- private readonly handleItemMouseDown;
6361
- protected willUpdate(changed: PropertyValues): void;
6362
- protected updated(changed: PropertyValues): void;
6363
- private renderItem;
6364
- private renderItems;
6365
- render(): import("lit-html").TemplateResult<1>;
6366
- }
6367
- }
6368
- declare module "components/slash-menu/slash-menu-controller" {
6369
- import type { TextField } from "utilities/caret-position";
6370
- import type { ReactiveController, ReactiveControllerHost } from 'lit';
6371
- import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
6372
- import type ZnSlashMenu from "components/slash-menu/slash-menu.component";
6373
- export interface SlashMenuControllerOptions {
6374
- /**
6375
- * Resolves the menu to render results into. Called the first time the menu is needed, so the host
6376
- * can render it lazily; may return a promise (e.g. after awaiting `updateComplete`).
6377
- */
6378
- menu: () => ZnSlashMenu | null | Promise<ZnSlashMenu | null>;
6379
- /** The available items, unfiltered. Receives the current query so lists can be resolved remotely. */
6380
- items: (query: string) => SlashMenuItem[] | Promise<SlashMenuItem[]>;
6381
- /** The characters that open the menu. Defaults to `/`. */
6382
- trigger?: () => string;
6383
- /** Called before an item is inserted. Return `false` to handle the item yourself. */
6384
- onSelect?: (item: SlashMenuItem, query: string) => boolean;
6385
- /** Called after an item's value has been written into the field. */
6386
- onInsert?: (item: SlashMenuItem, value: string) => void;
6387
- }
6388
- /**
6389
- * Drives a slash menu for a plain `<textarea>` or `<input>`: watches the caret for the trigger
6390
- * sequence, resolves and filters items, and inserts the chosen value.
6391
- *
6392
- * The host owns the field and the menu element; this controller owns the interaction.
6393
- */
6394
- export class SlashMenuController implements ReactiveController {
6395
- private readonly host;
6396
- private readonly options;
6397
- private readonly caretAnchor;
6398
- private field;
6399
- private menu;
6400
- private triggerIndex;
6401
- private query;
6402
- /** Trigger position the user dismissed with Escape; the menu stays shut until they move off it. */
6403
- private dismissedIndex;
6404
- private resolveToken;
6405
- private inserting;
6406
- private isOpen;
6407
- private listening;
6408
- /** Caret measurement is the expensive part of positioning, so the last one is reused. */
6409
- private measured?;
6410
- constructor(host: ReactiveControllerHost & HTMLElement, options: SlashMenuControllerOptions);
6411
- /** Whether the menu is currently showing. */
6412
- get open(): boolean;
6413
- hostConnected(): void;
6414
- hostDisconnected(): void;
6415
- /** Starts watching a field. Safe to call repeatedly with the same field. */
6416
- attach(field: TextField): void;
6417
- /** Stops watching the current field and closes the menu. */
6418
- detach(): void;
6419
- private addListeners;
6420
- private removeListeners;
6421
- /** Closes the menu without marking the trigger as dismissed. */
6422
- close(): void;
6423
- /** Opens the menu at the caret, as a toolbar button or keyboard shortcut would. */
6424
- requestOpen(): void;
6425
- private caretRect;
6426
- private readonly handleInput;
6427
- private readonly handleCaretMove;
6428
- private readonly handleKeyUp;
6429
- private readonly handleBlur;
6430
- private readonly handleScroll;
6431
- private readonly handleKeyDown;
6432
- private readonly handleItemSelect;
6433
- private detect;
6434
- private resolve;
6435
- private select;
6436
- private replace;
6437
- }
6438
- }
6439
- declare module "components/slash-item/slash-item.component" {
6440
- import ZincElement from "internal/zinc-element";
6441
- import type { CSSResultGroup } from 'lit';
6442
- import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
6443
- /**
6444
- * @summary Declares a single insertion for a slash menu. Renders nothing itself — it describes an
6445
- * entry for the component it is slotted into, e.g. `<zn-textarea>`'s `slash-items` slot.
6446
- * @documentation https://zinc.style/components/slash-item
6447
- * @status experimental
6448
- * @since 1.1
6449
- *
6450
- * @slot - The text to insert, for values that are long or span multiple lines. Ignored when the
6451
- * `value` attribute is set.
6452
- */
6453
- export default class ZnSlashItem extends ZincElement {
6454
- static styles: CSSResultGroup;
6455
- /** The text shown in the menu. */
6456
- label: string;
6457
- /** The text inserted into the field. Falls back to this element's text content. */
6458
- value: string;
6459
- /** Icon shown against the item, e.g. `tag@lu`. */
6460
- icon: string;
6461
- /** Supporting text shown under the label. */
6462
- description: string;
6463
- /** Extra terms the item can be found by, comma separated. */
6464
- keywords: string;
6465
- /** Heading the item is listed under. */
6466
- group: string;
6467
- /** Overrides the item's position in the menu. Lower sorts first. */
6468
- order: number;
6469
- /** Where the caret lands after insertion, as an offset into the inserted value. */
6470
- caretOffset: number;
6471
- /** Identifier passed through on `zn-slash-select`, for items that do something other than insert. */
6472
- action: string;
6473
- /** Listed, but not selectable. */
6474
- disabled: boolean;
6475
- /** The item as the slash menu consumes it. */
6476
- toSlashMenuItem(): SlashMenuItem;
6477
- private get insertValue();
6478
- render(): import("lit-html").TemplateResult<1>;
6479
- }
6480
- }
6481
- declare module "components/slash-item/index" {
6482
- import ZnSlashItem from "components/slash-item/slash-item.component";
6483
- export * from "components/slash-item/slash-item.component";
6484
- export default ZnSlashItem;
6485
- global {
6486
- interface HTMLElementTagNameMap {
6487
- 'zn-slash-item': ZnSlashItem;
6488
- }
6489
- }
6490
- }
6491
- declare module "components/slash-menu/index" {
6492
- import ZnSlashMenu from "components/slash-menu/slash-menu.component";
6493
- export * from "components/slash-menu/slash-menu.component";
6494
- export * from "components/slash-menu/slash-menu-controller";
6495
- export * from "components/slash-menu/slash-menu-items";
6496
- export default ZnSlashMenu;
6497
- global {
6498
- interface HTMLElementTagNameMap {
6499
- 'zn-slash-menu': ZnSlashMenu;
6500
- }
6501
- }
6502
- }
6503
6549
  declare module "components/textarea/textarea.component" {
6504
6550
  import { type CSSResultGroup } from 'lit';
6505
6551
  import { type SlashMenuItem } from "components/slash-menu/slash-menu-items";
@@ -8646,13 +8692,18 @@ declare module "components/translations/translations.component" {
8646
8692
  name: string;
8647
8693
  value: string;
8648
8694
  label: string;
8695
+ /**
8696
+ * Text shown below the field, describing how to fill it in. Applies to every language. If you need HTML, use the
8697
+ * `help-text` slot instead.
8698
+ */
8699
+ helpText: string;
8649
8700
  disabled: boolean;
8650
8701
  required: boolean;
8651
8702
  flush: boolean;
8652
8703
  inputType: 'select' | 'text' | 'number' | 'textarea';
8653
8704
  textareaRows: number | undefined;
8654
8705
  /**
8655
- * Quick insertions offered by the slash menu when `input-type` is `textarea`. Accepts a JSON array of items, or
8706
+ * Quick insertions offered by the slash menu on `text` and `textarea` inputs. Accepts a JSON array of items, or
8656
8707
  * the shorthand `Brand name={{BRAND_NAME}}, Support email={{SUPPORT_EMAIL}}`. Every language shares the list.
8657
8708
  */
8658
8709
  slashItems: SlashMenuItem[];
@@ -9185,6 +9236,7 @@ declare module "components/markdown-editor/index" {
9185
9236
  declare module "components/remarkd-editor/remarkd-editor.component" {
9186
9237
  import { type CSSResultGroup, type PropertyValues } from 'lit';
9187
9238
  import ZincElement from "internal/zinc-element";
9239
+ import ZnSlashMenu from "components/slash-menu/index";
9188
9240
  import type { ZincFormControl } from "internal/zinc-element";
9189
9241
  /**
9190
9242
  * @summary A Notion-style block editor for remarkd content. Blocks render inline; click one to edit its source.
@@ -9196,35 +9248,44 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9196
9248
  * @dependency zn-button-group
9197
9249
  * @dependency zn-icon
9198
9250
  * @dependency zn-file
9251
+ * @dependency zn-slash-menu
9199
9252
  *
9200
9253
  * @event zn-input - Emitted on each keystroke while editing a block.
9201
9254
  * @event zn-change - Emitted when a block edit is committed and the value changes.
9202
9255
  *
9203
9256
  * @csspart base - The component's base wrapper.
9204
9257
  * @csspart toolbar - The always-visible block-insert toolbar.
9258
+ * @csspart raw-toggle - The button that switches between the block view and the raw source view.
9205
9259
  * @csspart block - A rendered block wrapper.
9206
9260
  * @csspart rendered - The rendered remarkd output of a block.
9207
9261
  * @csspart input - The textarea shown while editing a block.
9208
- * @csspart slash-menu - The context menu opened by typing "/" in a block.
9262
+ * @csspart raw - The full-document textarea shown in raw source mode.
9263
+ * @csspart slash-menu - The `zn-slash-menu` opened by typing "/" in an empty block.
9209
9264
  * @csspart image-controls - The caption / alignment / size panel shown when an image block is clicked.
9210
9265
  */
9211
9266
  export default class ZnRemarkdEditor extends ZincElement implements ZincFormControl {
9212
9267
  static styles: CSSResultGroup;
9268
+ static dependencies: {
9269
+ 'zn-slash-menu': typeof ZnSlashMenu;
9270
+ };
9213
9271
  private readonly formControlController;
9272
+ private readonly slashController;
9214
9273
  private editingDraft;
9274
+ private rawEntryValue;
9215
9275
  private suppressValueSync;
9216
9276
  private suppressBlurCommit;
9217
9277
  private validationInput;
9278
+ private slashMenuElement;
9218
9279
  private blocks;
9219
9280
  private editingIndex;
9220
- private slashMenuOpen;
9221
- private slashQuery;
9222
- private slashActiveIndex;
9281
+ /** Renders the slash menu only once it has been needed. */
9282
+ private hasSlashMenu;
9223
9283
  private imagePickerIndex;
9224
9284
  private imageEdit;
9225
9285
  private dropIndicator;
9226
9286
  private dragIndex;
9227
9287
  private editShell;
9288
+ private rawMode;
9228
9289
  private pendingDragHandle;
9229
9290
  private dragStartX;
9230
9291
  private dragStartY;
@@ -9243,6 +9304,8 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9243
9304
  * to `uploadUrl` and the returned `uploadPath` is embedded as the image URL.
9244
9305
  */
9245
9306
  attachmentUrl: string;
9307
+ /** Adds a toolbar toggle that swaps the block view for the full remarkd source. */
9308
+ allowRaw: boolean;
9246
9309
  /** Makes the editor required for form submission. */
9247
9310
  required: boolean;
9248
9311
  /** Makes the editor read-only. */
@@ -9257,7 +9320,7 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9257
9320
  setCustomValidity(message: string): void;
9258
9321
  /** Starts editing the first block, or a new block if the document is empty. */
9259
9322
  focus(): void;
9260
- /** Commits any in-progress block edit. */
9323
+ /** Commits any in-progress block or raw edit. */
9261
9324
  blur(): void;
9262
9325
  protected firstUpdated(_changedProperties: PropertyValues): void;
9263
9326
  disconnectedCallback(): void;
@@ -9300,10 +9363,13 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9300
9363
  private handleEditBlur;
9301
9364
  /** Commits the in-progress edit; returns the index after the committed parts. */
9302
9365
  private commitEdit;
9303
- private get filteredSlashItems();
9304
9366
  private handleDraftInput;
9305
9367
  private handleEditKeydown;
9306
- private applySlashItem;
9368
+ /** Whether the block being edited is nothing but the slash command. */
9369
+ private isSlashBlock;
9370
+ private mountSlashMenu;
9371
+ /** Returns false for items the controller should not insert text for. */
9372
+ private handleSlashSelect;
9307
9373
  private handleEditPaste;
9308
9374
  private handleDragOver;
9309
9375
  private handleDrop;
@@ -9321,11 +9387,25 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9321
9387
  private insertImage;
9322
9388
  private uploadImage;
9323
9389
  private autosize;
9390
+ private toggleRawMode;
9391
+ private focusRaw;
9392
+ /**
9393
+ * Raw mode keeps the whole document in one textarea, so the textarea — not
9394
+ * the block list — is authoritative while it is open: re-splitting on every
9395
+ * keystroke would normalise blank lines out from under the cursor.
9396
+ */
9397
+ private handleRawInput;
9398
+ /**
9399
+ * Re-splits the raw source into blocks. Not `updateBlocks` — that only
9400
+ * reports a change when the re-join differs from the value, and raw edits
9401
+ * have already written straight to the value.
9402
+ */
9403
+ private commitRaw;
9324
9404
  private handleToolbarInsert;
9325
- private renderSlashMenu;
9326
9405
  private renderImageControls;
9327
9406
  private renderBlock;
9328
9407
  render(): import("lit-html").TemplateResult<1>;
9408
+ private renderRaw;
9329
9409
  /** The block views, with the inline image picker spliced in when active. */
9330
9410
  private renderBody;
9331
9411
  private renderImagePicker;