@qalma/kit 0.4.0 → 0.5.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.
- package/README.md +15 -4
- package/fesm2022/qalma-kit.mjs +3 -2
- package/fesm2022/qalma-kit.mjs.map +1 -1
- package/package.json +1 -1
- package/types/qalma-kit.d.ts +4 -3
- package/types/qalma-kit.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -33,9 +33,19 @@ Peer dependencies:
|
|
|
33
33
|
- `@ng-icons/core`
|
|
34
34
|
- `@ng-icons/lucide`
|
|
35
35
|
|
|
36
|
-
The kit
|
|
37
|
-
contract below. If you already use
|
|
38
|
-
familiar.
|
|
36
|
+
The kit does not ship a compiled stylesheet. It expects your app to provide
|
|
37
|
+
Tailwind utilities and the CSS token contract below. If you already use
|
|
38
|
+
shadcn-style tokens, the defaults should feel familiar.
|
|
39
|
+
|
|
40
|
+
With Tailwind v4, point Tailwind at the installed package so it generates the
|
|
41
|
+
utilities used inside kit components:
|
|
42
|
+
|
|
43
|
+
```css
|
|
44
|
+
@import 'tailwindcss';
|
|
45
|
+
|
|
46
|
+
/* Adjust the path if your global stylesheet is not src/styles.css. */
|
|
47
|
+
@source '../node_modules/@qalma/kit';
|
|
48
|
+
```
|
|
39
49
|
|
|
40
50
|
## Theming
|
|
41
51
|
|
|
@@ -43,10 +53,11 @@ The kit does not ship a fixed brand. Components read design tokens through
|
|
|
43
53
|
Tailwind utility names such as `bg-popover`, `text-muted-foreground`,
|
|
44
54
|
`border-border`, and `ring-ring`.
|
|
45
55
|
|
|
46
|
-
|
|
56
|
+
Then expose those tokens with `@theme`:
|
|
47
57
|
|
|
48
58
|
```css
|
|
49
59
|
@import 'tailwindcss';
|
|
60
|
+
@source '../node_modules/@qalma/kit';
|
|
50
61
|
|
|
51
62
|
@theme {
|
|
52
63
|
--color-background: var(--background);
|
package/fesm2022/qalma-kit.mjs
CHANGED
|
@@ -13,11 +13,12 @@ import { twMerge } from 'tailwind-merge';
|
|
|
13
13
|
/**
|
|
14
14
|
* Default styling for a toolbar command button. Icon-only, square, and driven
|
|
15
15
|
* entirely by the host's shadcn-style design tokens (`text-muted-foreground`,
|
|
16
|
-
* `bg-secondary`, `bg-accent-subtle`…) so it themes with the
|
|
16
|
+
* `bg-card`, `bg-secondary`, `bg-accent-subtle`…) so it themes with the
|
|
17
|
+
* surrounding app.
|
|
17
18
|
* The `qalma-command-active` class is toggled by the `QalmaCommand` directive
|
|
18
19
|
* when the underlying command is active.
|
|
19
20
|
*/
|
|
20
|
-
const TOOLBAR_BUTTON_CLASS = 'inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-
|
|
21
|
+
const TOOLBAR_BUTTON_CLASS = 'inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-border bg-card text-muted-foreground transition hover:border-accent/50 hover:bg-secondary hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45 [&.qalma-command-active]:border-accent/40 [&.qalma-command-active]:bg-accent-subtle [&.qalma-command-active]:text-accent';
|
|
21
22
|
/**
|
|
22
23
|
* Generic, declarative toolbar button for a single editor command.
|
|
23
24
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qalma-kit.mjs","sources":["../../../../libs/ui-kit/src/lib/toolbar-button.ts","../../../../libs/ui-kit/src/lib/toolbar-commands.ts","../../../../libs/ui-kit/src/lib/toolbar-registry.ts","../../../../libs/ui-kit/src/lib/toolbar-icons.ts","../../../../libs/ui-kit/src/lib/cn.ts","../../../../libs/ui-kit/src/lib/button.ts","../../../../libs/ui-kit/src/lib/drag-handle.ts","../../../../libs/ui-kit/src/lib/mention-menu.ts","../../../../libs/ui-kit/src/lib/slash-command-menu.ts","../../../../libs/ui-kit/src/lib/link-popover.ts","../../../../libs/ui-kit/src/lib/contextual-toolbar.ts","../../../../libs/ui-kit/src/index.ts","../../../../libs/ui-kit/src/qalma-kit.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { NgIcon } from '@ng-icons/core';\nimport { QalmaCommand } from '@qalma/editor';\n\n/**\n * Default styling for a toolbar command button. Icon-only, square, and driven\n * entirely by the host's shadcn-style design tokens (`text-muted-foreground`,\n * `bg-secondary`, `bg-accent-subtle`…) so it themes with the surrounding app.\n * The `qalma-command-active` class is toggled by the `QalmaCommand` directive\n * when the underlying command is active.\n */\nexport const TOOLBAR_BUTTON_CLASS =\n 'inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-transparent text-muted-foreground transition hover:bg-secondary hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45 [&.qalma-command-active]:border-accent/40 [&.qalma-command-active]:bg-accent-subtle [&.qalma-command-active]:text-accent';\n\n/**\n * Generic, declarative toolbar button for a single editor command.\n *\n * Renders a native `<button>` wired to the `QalmaCommand` directive (execute /\n * active / disabled / aria) with an `<ng-icon>`, so a whole toolbar becomes a\n * list of `<qalma-toolbar-button command icon label />` instead of the\n * six-line `<button qalmaCommand><ng-icon></button>` block repeated per\n * command. The host uses `display: contents` so the inner button participates\n * directly in the surrounding toolbar's flex layout.\n *\n * Icons resolve from the `NgIcon` provider scope of the surrounding component\n * (register them with `provideIcons({ … })` as usual).\n */\n@Component({\n selector: 'qalma-toolbar-button',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon, QalmaCommand],\n host: {\n class: 'contents',\n },\n template: `\n <button\n type=\"button\"\n [qalmaCommand]=\"command()\"\n [qalmaCommandValue]=\"value()\"\n [class]=\"buttonClass\"\n [title]=\"label()\"\n [attr.aria-label]=\"label()\"\n >\n <ng-icon [class]=\"iconClass()\" [name]=\"icon()\" aria-hidden=\"true\" />\n </button>\n `,\n})\nexport class QalmaToolbarButton {\n /** Command name to execute, e.g. `toggleBold`. */\n readonly command = input.required<string>();\n /** Optional command payload (forwarded to `qalmaCommandValue`). */\n readonly value = input<unknown>();\n /** Lucide (or any registered) icon name, e.g. `lucideBold`. */\n readonly icon = input.required<string>();\n /** Accessible name — used for both `title` and `aria-label`. */\n readonly label = input.required<string>();\n /** Optional icon-size class override (default: `text-[0.9rem]`). */\n readonly iconClass = input('text-[0.9rem]');\n\n protected readonly buttonClass = TOOLBAR_BUTTON_CLASS;\n}\n","import type { TemplateRef } from '@angular/core';\n\n/**\n * A single command button in a toolbar registry: which editor command to run,\n * which icon to show, and its accessible label. `value` is forwarded to the\n * command as its payload when present.\n */\nexport interface ToolbarCommandItem {\n readonly command: string;\n readonly icon: string;\n readonly label: string;\n readonly value?: unknown;\n}\n\n/**\n * An escape hatch for controls that are not a plain command button (color\n * pickers, upload buttons, a language `<select>`…). The consumer supplies an\n * `<ng-template>` and the toolbar renders it inline at this position.\n */\nexport interface ToolbarTemplateItem {\n readonly template: TemplateRef<unknown>;\n}\n\nexport type ToolbarItem = ToolbarCommandItem | ToolbarTemplateItem;\n\n/** One separator-delimited run of items. Empty groups render nothing. */\nexport type ToolbarGroup = readonly ToolbarItem[];\n\nexport function isToolbarCommandItem(\n item: ToolbarItem,\n): item is ToolbarCommandItem {\n return 'command' in item;\n}\n\n// ---------------------------------------------------------------------------\n// Default command fragments — the declarative source of truth for the standard\n// editor toolbar, reusable across consumers (playground, sandbox, downstream\n// apps). Compose them into `ToolbarGroup[]` and hand them to\n// `<qalma-toolbar-registry>`; interleave custom controls with `ToolbarTemplateItem`.\n// ---------------------------------------------------------------------------\n\nexport const QALMA_TOOLBAR_HEADINGS: readonly ToolbarCommandItem[] = [\n { command: 'setParagraph', icon: 'lucidePilcrow', label: 'Paragraph' },\n { command: 'toggleHeading1', icon: 'lucideHeading1', label: 'Heading 1' },\n { command: 'toggleHeading2', icon: 'lucideHeading2', label: 'Heading 2' },\n { command: 'toggleHeading3', icon: 'lucideHeading3', label: 'Heading 3' },\n];\n\nexport const QALMA_TOOLBAR_INLINE_MARKS: readonly ToolbarCommandItem[] = [\n { command: 'toggleBold', icon: 'lucideBold', label: 'Bold' },\n { command: 'toggleItalic', icon: 'lucideItalic', label: 'Italic' },\n { command: 'toggleUnderline', icon: 'lucideUnderline', label: 'Underline' },\n {\n command: 'toggleStrike',\n icon: 'lucideStrikethrough',\n label: 'Strikethrough',\n },\n { command: 'toggleInlineCode', icon: 'lucideCode', label: 'Inline code' },\n { command: 'toggleMonospace', icon: 'lucideLetterText', label: 'Monospace' },\n { command: 'toggleSubscript', icon: 'lucideSubscript', label: 'Subscript' },\n {\n command: 'toggleSuperscript',\n icon: 'lucideSuperscript',\n label: 'Superscript',\n },\n];\n\nexport const QALMA_TOOLBAR_ALIGN: readonly ToolbarCommandItem[] = [\n { command: 'setTextAlignLeft', icon: 'lucideAlignLeft', label: 'Align left' },\n {\n command: 'setTextAlignCenter',\n icon: 'lucideAlignCenter',\n label: 'Align center',\n },\n {\n command: 'setTextAlignRight',\n icon: 'lucideAlignRight',\n label: 'Align right',\n },\n {\n command: 'setTextAlignJustify',\n icon: 'lucideAlignJustify',\n label: 'Justify',\n },\n];\n\nexport const QALMA_TOOLBAR_LISTS: readonly ToolbarCommandItem[] = [\n { command: 'toggleBulletList', icon: 'lucideList', label: 'Bullet list' },\n {\n command: 'toggleOrderedList',\n icon: 'lucideListOrdered',\n label: 'Ordered list',\n },\n { command: 'toggleTaskList', icon: 'lucideListTodo', label: 'Task list' },\n { command: 'liftListItem', icon: 'lucideOutdent', label: 'Outdent' },\n { command: 'sinkListItem', icon: 'lucideIndent', label: 'Indent' },\n { command: 'toggleBlockquote', icon: 'lucideTextQuote', label: 'Blockquote' },\n { command: 'toggleCodeBlock', icon: 'lucideSquareCode', label: 'Code block' },\n];\n\n/** Always-available table entry point (inserting a new table). */\nexport const QALMA_TOOLBAR_TABLE_INSERT: ToolbarCommandItem = {\n command: 'insertTable',\n icon: 'lucideTable',\n label: 'Insert table',\n};\n\n/** Table editing commands — only meaningful while the selection is in a table. */\nexport const QALMA_TOOLBAR_TABLE_OPS: readonly ToolbarCommandItem[] = [\n {\n command: 'addRowAfter',\n icon: 'lucideBetweenHorizontalEnd',\n label: 'Add row',\n },\n {\n command: 'addColumnAfter',\n icon: 'lucideBetweenVerticalEnd',\n label: 'Add column',\n },\n { command: 'deleteRow', icon: 'lucideRows3', label: 'Delete row' },\n { command: 'deleteColumn', icon: 'lucideColumns3', label: 'Delete column' },\n {\n command: 'toggleHeaderRow',\n icon: 'lucideHeading',\n label: 'Toggle header row',\n },\n { command: 'deleteTable', icon: 'lucideTrash2', label: 'Delete table' },\n];\n\nexport const QALMA_TOOLBAR_HISTORY: readonly ToolbarCommandItem[] = [\n { command: 'undo', icon: 'lucideUndo2', label: 'Undo' },\n { command: 'redo', icon: 'lucideRedo2', label: 'Redo' },\n];\n\n/** Standalone command that usually sits alongside the color controls. */\nexport const QALMA_TOOLBAR_CLEAR_FORMATTING: ToolbarCommandItem = {\n command: 'clearFormatting',\n icon: 'lucideEraser',\n label: 'Clear formatting',\n};\n\n/** Standalone command that usually sits alongside the link/insert controls. */\nexport const QALMA_TOOLBAR_UNSET_LINK: ToolbarCommandItem = {\n command: 'unsetLink',\n icon: 'lucideUnlink',\n label: 'Unlink',\n};\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n TemplateRef,\n computed,\n input,\n} from '@angular/core';\n\nimport { QalmaToolbarButton } from './toolbar-button';\nimport {\n ToolbarCommandItem,\n ToolbarGroup,\n ToolbarItem,\n ToolbarTemplateItem,\n isToolbarCommandItem,\n} from './toolbar-commands';\n\n/** Vertical divider rendered between non-empty toolbar groups. */\nexport const TOOLBAR_SEPARATOR_CLASS =\n 'mx-0.5 h-5 w-px shrink-0 self-center bg-border';\n\n/**\n * Renders a declarative toolbar registry: an ordered list of groups, each a\n * list of command buttons and/or inline custom-control templates, with a\n * separator drawn between non-empty groups.\n *\n * Meant to sit inside the editor's `<qalma-toolbar>` (which owns the\n * `role=\"toolbar\"` semantics); the host uses `display: contents` so the\n * rendered buttons participate directly in that container's flex layout.\n *\n * ```html\n * <qalma-toolbar class=\"flex …\">\n * <ng-template #colors> … custom controls … </ng-template>\n * <qalma-toolbar-registry [groups]=\"[headings, marks, [{ template: colors }]]\" />\n * </qalma-toolbar>\n * ```\n */\n@Component({\n selector: 'qalma-toolbar-registry',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgTemplateOutlet, QalmaToolbarButton],\n host: {\n class: 'contents',\n },\n template: `\n @for (group of visibleGroups(); track $index; let first = $first) {\n @if (!first) {\n <span [class]=\"separatorClass()\" aria-hidden=\"true\"></span>\n }\n @for (item of group; track $index) {\n @if (asCommand(item); as command) {\n <qalma-toolbar-button\n [command]=\"command.command\"\n [value]=\"command.value\"\n [icon]=\"command.icon\"\n [label]=\"command.label\"\n />\n } @else {\n <ng-container [ngTemplateOutlet]=\"asTemplate(item)\" />\n }\n }\n }\n `,\n})\nexport class QalmaToolbarRegistry {\n readonly groups = input.required<readonly ToolbarGroup[]>();\n readonly separatorClass = input(TOOLBAR_SEPARATOR_CLASS);\n\n /** Drop empty groups so they neither render content nor a dangling separator. */\n protected readonly visibleGroups = computed(() =>\n this.groups().filter((group) => group.length > 0),\n );\n\n protected asCommand(item: ToolbarItem): ToolbarCommandItem | null {\n return isToolbarCommandItem(item) ? item : null;\n }\n\n protected asTemplate(item: ToolbarItem): TemplateRef<unknown> {\n return (item as ToolbarTemplateItem).template;\n }\n}\n","import { provideIcons } from '@ng-icons/core';\nimport {\n lucideAlignCenter,\n lucideAlignJustify,\n lucideAlignLeft,\n lucideAlignRight,\n lucideBetweenHorizontalEnd,\n lucideBetweenVerticalEnd,\n lucideBold,\n lucideCode,\n lucideColumns3,\n lucideEraser,\n lucideHeading,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideIndent,\n lucideItalic,\n lucideLetterText,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideOutdent,\n lucidePilcrow,\n lucideRedo2,\n lucideRows3,\n lucideSquareCode,\n lucideStrikethrough,\n lucideSubscript,\n lucideSuperscript,\n lucideTable,\n lucideTextQuote,\n lucideTrash2,\n lucideUnderline,\n lucideUndo2,\n lucideUnlink,\n} from '@ng-icons/lucide';\n\n/**\n * Registers the Lucide icons referenced by the default toolbar command\n * fragments (`QALMA_TOOLBAR_*`), so consumers can wire the standard toolbar\n * without re-declaring the icon set:\n *\n * ```ts\n * providers: [provideQalmaToolbarIcons()]\n * ```\n *\n * Add your own `provideIcons({ … })` alongside it for any custom controls\n * (color pickers, upload buttons…) that live outside the command registry.\n */\nexport function provideQalmaToolbarIcons() {\n return provideIcons({\n lucideAlignCenter,\n lucideAlignJustify,\n lucideAlignLeft,\n lucideAlignRight,\n lucideBetweenHorizontalEnd,\n lucideBetweenVerticalEnd,\n lucideBold,\n lucideCode,\n lucideColumns3,\n lucideEraser,\n lucideHeading,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideIndent,\n lucideItalic,\n lucideLetterText,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideOutdent,\n lucidePilcrow,\n lucideRedo2,\n lucideRows3,\n lucideSquareCode,\n lucideStrikethrough,\n lucideSubscript,\n lucideSuperscript,\n lucideTable,\n lucideTextQuote,\n lucideTrash2,\n lucideUnderline,\n lucideUndo2,\n lucideUnlink,\n });\n}\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { Directive, ElementRef, computed, inject, input } from '@angular/core';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from './cn';\n\nexport const buttonVariants = cva(\n 'inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 [&_ng-icon]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n outline:\n 'border border-border bg-card text-foreground hover:bg-secondary hover:text-secondary-foreground',\n ghost:\n 'text-foreground hover:bg-secondary hover:text-secondary-foreground',\n accent: 'bg-accent text-accent-foreground hover:bg-accent/90',\n link: 'text-accent underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 rounded-md px-3 text-xs',\n lg: 'h-11 rounded-md px-6 text-base',\n icon: 'h-9 w-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport type ButtonVariant = NonNullable<\n VariantProps<typeof buttonVariants>['variant']\n>;\nexport type ButtonSize = NonNullable<\n VariantProps<typeof buttonVariants>['size']\n>;\n\n/**\n * Headless-styled button directive so it composes onto native `<button>` and\n * `<a>` elements while reading from the host's Tailwind design tokens.\n */\n@Directive({\n selector: 'button[qalmaBtn], a[qalmaBtn]',\n host: {\n '[class]': 'computedClass()',\n },\n})\nexport class QalmaButton {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly initialClass =\n this.host.nativeElement.getAttribute('class') ?? '';\n\n readonly variant = input<ButtonVariant>('default');\n readonly size = input<ButtonSize>('default');\n\n protected readonly computedClass = computed(() =>\n cn(\n buttonVariants({ variant: this.variant(), size: this.size() }),\n this.initialClass,\n ),\n );\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { QalmaEditorController } from '@qalma/editor';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n lucideArrowDown,\n lucideArrowUp,\n lucideCopy,\n lucideGripVertical,\n lucideMousePointer2,\n lucideTrash2,\n} from '@ng-icons/lucide';\n\nimport {\n DismissibleOverlay,\n QalmaDragBlockHighlight,\n QalmaDragDropIndicator,\n QalmaDragHandleView,\n} from '@qalma/kit/headless';\n\nimport { QalmaButton } from './button';\n\nexport interface QalmaDragStart {\n event: PointerEvent;\n handle: QalmaDragHandleView;\n}\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon, QalmaButton],\n providers: [\n provideIcons({\n lucideArrowDown,\n lucideArrowUp,\n lucideCopy,\n lucideGripVertical,\n lucideMousePointer2,\n lucideTrash2,\n }),\n ],\n selector: 'qalma-drag-handle',\n template: `\n @if (draggedBlockHighlight(); as highlight) {\n <div\n data-qalma-dragging-block-highlight\n class=\"pointer-events-none fixed left-0 top-0 z-20 rounded-md border border-accent bg-accent-subtle/80 opacity-70 shadow-md will-change-transform\"\n [style.transform]=\"highlight.transform\"\n [style.width.px]=\"highlight.width\"\n [style.height.px]=\"highlight.height\"\n ></div>\n }\n\n @if (dropIndicator(); as indicator) {\n <div\n data-qalma-drag-drop-line\n class=\"pointer-events-none fixed left-0 top-0 z-40 h-0.5 rounded-full bg-accent shadow-md will-change-transform\"\n [style.transform]=\"indicator.transform\"\n [style.width.px]=\"indicator.width\"\n ></div>\n }\n\n @if (handle(); as handle) {\n <div\n data-qalma-drag-handle\n class=\"fixed left-0 top-0 z-30 flex items-start gap-1 will-change-transform\"\n tabindex=\"-1\"\n [style.transform]=\"handle.transform\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown.escape)=\"dismissFromKeyboard($event)\"\n >\n <button\n qalmaBtn\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n class=\"!h-[1.85rem] !w-[1.85rem] cursor-grab rounded-[0.4rem] border border-transparent bg-card/95 text-muted-foreground shadow-sm active:cursor-grabbing hover:border-border hover:bg-secondary hover:text-foreground\"\n [class.border-accent]=\"menuOpen()\"\n [class.text-accent]=\"menuOpen()\"\n (pointerdown)=\"startDrag($event, handle)\"\n (click)=\"toggleMenu()\"\n title=\"Block actions\"\n aria-label=\"Block actions\"\n [attr.aria-expanded]=\"menuOpen()\"\n >\n <ng-icon\n class=\"text-[0.9rem]\"\n name=\"lucideGripVertical\"\n aria-hidden=\"true\"\n />\n </button>\n\n @if (menuOpen()) {\n <div\n role=\"menu\"\n aria-label=\"Block actions\"\n class=\"w-44 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg\"\n >\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!canExecute('selectBlock', handle)\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('selectBlock', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideMousePointer2\" aria-hidden=\"true\" />\n Select block\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!handle.canMoveUp\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('moveBlockUp', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideArrowUp\" aria-hidden=\"true\" />\n Move up\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!handle.canMoveDown\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('moveBlockDown', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideArrowDown\" aria-hidden=\"true\" />\n Move down\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!canExecute('duplicateBlock', handle)\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('duplicateBlock', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideCopy\" aria-hidden=\"true\" />\n Duplicate\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-destructive transition hover:bg-destructive/10 disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!canExecute('deleteBlock', handle)\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('deleteBlock', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideTrash2\" aria-hidden=\"true\" />\n Delete\n </button>\n </div>\n }\n </div>\n }\n `,\n})\nexport class QalmaDragHandle {\n readonly editor = input.required<QalmaEditorController>();\n readonly handle = input<QalmaDragHandleView | null>(null);\n readonly dropIndicator = input<QalmaDragDropIndicator | null>(null);\n readonly draggedBlockHighlight = input<QalmaDragBlockHighlight | null>(\n null,\n );\n readonly dismiss = output<void>();\n readonly dragStart = output<QalmaDragStart>();\n\n protected readonly menuOpen = signal(false);\n\n constructor() {\n // Close the block-actions menu on an outside pointerdown or Escape. A click\n // on the handle button or the menu itself (both under `[data-qalma-drag-handle]`)\n // is treated as inside, so it doesn't self-dismiss. Connected for the\n // component's lifetime; the callback is a no-op while the menu is closed.\n new DismissibleOverlay({\n isInside: (target) =>\n target instanceof Element &&\n !!target.closest('[data-qalma-drag-handle]'),\n onDismiss: () => this.menuOpen.set(false),\n }).connect(inject(DestroyRef));\n }\n\n protected toggleMenu(): void {\n this.menuOpen.update((open) => !open);\n }\n\n protected startDrag(\n event: PointerEvent,\n handle: QalmaDragHandleView,\n ): void {\n this.menuOpen.set(false);\n this.dragStart.emit({ event, handle });\n }\n\n protected canExecute(\n command: string,\n handle: QalmaDragHandleView,\n ): boolean {\n return this.editor().canExecute(command, handle.target);\n }\n\n protected execute(command: string, handle: QalmaDragHandleView): void {\n if (this.editor().execute(command, handle.target)) {\n this.dismissHandle();\n }\n }\n\n protected preserveSelection(event: MouseEvent): void {\n event.preventDefault();\n }\n\n protected dismissFromKeyboard(event: Event): void {\n event.preventDefault();\n this.dismissHandle();\n }\n\n protected dismissHandle(): void {\n this.menuOpen.set(false);\n this.dismiss.emit();\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\n\nimport { QalmaSuggestionMenu } from '@qalma/kit/headless';\n\nexport interface QalmaMentionOption {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n}\n\n/**\n * Caret-anchored mention suggestion menu: an avatar-initial list with a loading\n * state. Positioning, keyboard handling and active highlighting come from\n * {@link QalmaSuggestionMenu}; feed it a `placement` (see `flipAbovePlacement`)\n * and the filtered `suggestions`.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'qalma-mention-menu',\n template: `\n @if (placement(); as placement) {\n <div\n role=\"listbox\"\n aria-label=\"Mention suggestions\"\n class=\"fixed z-20 w-[min(280px,calc(100vw-24px))] overflow-hidden rounded-md border border-border bg-popover p-1 text-sm text-popover-foreground shadow-lg outline-none\"\n [style.left.px]=\"placement.left\"\n [style.top.px]=\"placement.top\"\n [style.bottom.px]=\"placement.bottom\"\n [style.max-height.px]=\"placement.maxHeight\"\n >\n @if (loading()) {\n <div\n class=\"flex items-center gap-2 px-2 py-2 text-sm text-muted-foreground\"\n >\n <span\n class=\"size-7 animate-pulse rounded-sm border border-border bg-secondary\"\n aria-hidden=\"true\"\n ></span>\n <span>Loading…</span>\n </div>\n } @else {\n <div class=\"max-h-full overflow-y-auto\">\n @for (\n option of suggestions();\n track option.id;\n let index = $index\n ) {\n <button\n type=\"button\"\n role=\"option\"\n [attr.data-suggestion-index]=\"index\"\n class=\"group grid h-12 w-full min-w-0 cursor-pointer grid-cols-[1.75rem_minmax(0,1fr)] items-center gap-2 rounded-sm px-2 text-left transition-colors hover:bg-accent-subtle hover:text-foreground focus:bg-accent-subtle focus:text-foreground focus:outline-none\"\n [class.bg-accent-subtle]=\"index === activeIndex()\"\n [class.text-foreground]=\"index === activeIndex()\"\n [attr.aria-selected]=\"index === activeIndex()\"\n [attr.tabindex]=\"index === activeIndex() ? 0 : -1\"\n (mouseenter)=\"activate.emit(index)\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown)=\"handleOptionKeydown($event, option, index)\"\n (click)=\"pick.emit(option)\"\n >\n <span\n class=\"flex size-7 items-center justify-center rounded-sm border border-border bg-card text-xs font-semibold text-foreground\"\n [class.border-accent]=\"index === activeIndex()\"\n [class.bg-background]=\"index === activeIndex()\"\n [class.text-accent]=\"index === activeIndex()\"\n aria-hidden=\"true\"\n >\n {{ option.label.slice(0, 1) }}\n </span>\n <span class=\"min-w-0\">\n <span class=\"block truncate font-medium leading-5\">{{\n option.label\n }}</span>\n @if (index === activeIndex()) {\n <span\n class=\"block truncate text-xs leading-4 text-foreground\"\n >\n {{ option.description }}\n </span>\n } @else {\n <span\n class=\"block truncate text-xs leading-4 text-muted-foreground group-hover:text-foreground group-focus:text-foreground\"\n >\n {{ option.description }}\n </span>\n }\n </span>\n </button>\n }\n </div>\n }\n </div>\n }\n `,\n})\nexport class QalmaMentionMenu extends QalmaSuggestionMenu<QalmaMentionOption> {\n readonly suggestions = input<readonly QalmaMentionOption[]>([]);\n readonly loading = input(false);\n\n protected readonly optionList = this.suggestions;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n effect,\n input,\n} from '@angular/core';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n lucideCode,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideMinus,\n lucidePilcrow,\n lucideSquareCode,\n lucideTable,\n lucideTextQuote,\n} from '@ng-icons/lucide';\nimport { QalmaCommandValue } from '@qalma/editor';\n\nimport { QalmaSuggestionMenu } from '@qalma/kit/headless';\n\nexport interface QalmaSlashCommandOption {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n readonly icon: string;\n readonly shortcut: string;\n /** Editor command to run when the option is picked. */\n readonly command: string;\n readonly value?: QalmaCommandValue;\n readonly placement?: 'block' | 'inline';\n /** Extra terms the consumer can match against when filtering. */\n readonly keywords: readonly string[];\n}\n\n/**\n * Caret-anchored slash-command menu: an icon + shortcut list with a \"Commands\"\n * header and an Escape hint footer, scrolling the active option into view.\n * Positioning, keyboard handling and active highlighting come from\n * {@link QalmaSuggestionMenu}; feed it a `placement` (see `flipAbovePlacement`)\n * and the filtered `options`. Ships the default block-command icon set.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon],\n providers: [\n provideIcons({\n lucideCode,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideMinus,\n lucidePilcrow,\n lucideSquareCode,\n lucideTable,\n lucideTextQuote,\n }),\n ],\n selector: 'qalma-slash-command-menu',\n template: `\n @if (placement(); as placement) {\n <div\n role=\"listbox\"\n aria-label=\"Slash command suggestions\"\n class=\"fixed z-20 flex w-[min(320px,calc(100vw-24px))] flex-col overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg outline-none\"\n [style.left.px]=\"placement.left\"\n [style.top.px]=\"placement.top\"\n [style.bottom.px]=\"placement.bottom\"\n [style.max-height.px]=\"placement.maxHeight\"\n >\n <div\n class=\"shrink-0 px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\"\n >\n Commands\n </div>\n <div data-suggestion-options class=\"min-h-0 flex-1 overflow-y-auto\">\n @for (option of options(); track option.id; let index = $index) {\n <button\n type=\"button\"\n role=\"option\"\n [attr.data-suggestion-index]=\"index\"\n class=\"group grid h-11 w-full min-w-0 cursor-pointer grid-cols-[1.75rem_minmax(0,1fr)_auto] items-center gap-2 rounded-sm px-2 text-left text-sm transition-colors hover:bg-accent-subtle hover:text-foreground focus:bg-accent-subtle focus:text-foreground focus:outline-none\"\n [class.bg-accent-subtle]=\"index === activeIndex()\"\n [class.text-foreground]=\"index === activeIndex()\"\n [attr.aria-selected]=\"index === activeIndex()\"\n [attr.tabindex]=\"index === activeIndex() ? 0 : -1\"\n (mouseenter)=\"activate.emit(index)\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown)=\"handleOptionKeydown($event, option, index)\"\n (click)=\"pick.emit(option)\"\n >\n <span\n class=\"flex size-7 items-center justify-center rounded-sm border border-border bg-card text-[14px] text-foreground\"\n [class.border-accent]=\"index === activeIndex()\"\n [class.bg-background]=\"index === activeIndex()\"\n [class.text-accent]=\"index === activeIndex()\"\n >\n <ng-icon [name]=\"option.icon\" aria-hidden=\"true\" />\n </span>\n <span class=\"min-w-0\">\n <span class=\"block truncate font-medium leading-5\">{{\n option.label\n }}</span>\n @if (index === activeIndex()) {\n <span\n class=\"block truncate text-xs leading-4 text-foreground\"\n >\n {{ option.description }}\n </span>\n } @else {\n <span\n class=\"block truncate text-xs leading-4 text-muted-foreground group-hover:text-foreground group-focus:text-foreground\"\n >\n {{ option.description }}\n </span>\n }\n </span>\n <kbd\n class=\"rounded-sm border border-border bg-card px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground\"\n [class.border-accent]=\"index === activeIndex()\"\n [class.bg-background]=\"index === activeIndex()\"\n [class.text-accent]=\"index === activeIndex()\"\n >\n {{ option.shortcut }}\n </kbd>\n </button>\n }\n </div>\n <div\n class=\"mt-1 flex h-8 shrink-0 items-center justify-between border-t border-border px-2 text-[11px] text-muted-foreground\"\n >\n <span>Close menu</span>\n <kbd\n class=\"rounded-sm border border-border bg-card px-1.5 py-0.5 font-mono\"\n >esc</kbd\n >\n </div>\n </div>\n }\n `,\n})\nexport class QalmaSlashCommandMenu extends QalmaSuggestionMenu<QalmaSlashCommandOption> {\n readonly options = input<readonly QalmaSlashCommandOption[]>([]);\n\n protected readonly optionList = this.options;\n\n constructor() {\n super();\n\n effect(() => {\n const activeIndex = this.activeIndex();\n\n this.options();\n queueMicrotask(() => this.scrollOptionIntoView(activeIndex));\n });\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n input,\n output,\n} from '@angular/core';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n lucideCheck,\n lucideExternalLink,\n lucideLink,\n lucidePencil,\n lucideUnlink,\n lucideX,\n} from '@ng-icons/lucide';\n\nimport { LinkPopover } from '@qalma/kit/headless';\n\nimport { QalmaButton } from './button';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon, QalmaButton],\n providers: [\n provideIcons({\n lucideCheck,\n lucideExternalLink,\n lucideLink,\n lucidePencil,\n lucideUnlink,\n lucideX,\n }),\n ],\n selector: 'qalma-link-popover',\n template: `\n @if (popover(); as popover) {\n <div\n data-qalma-link-popover\n role=\"dialog\"\n aria-label=\"Link preview\"\n class=\"fixed z-20 w-[min(360px,calc(100vw-32px))] rounded-md border border-border bg-popover p-1.5 text-sm text-popover-foreground shadow-lg outline-none\"\n [style.left.px]=\"popover.left\"\n [style.top.px]=\"popover.top\"\n (mouseenter)=\"keepOpen.emit()\"\n (mouseleave)=\"scheduleHide.emit()\"\n (focusin)=\"keepOpen.emit()\"\n (focusout)=\"scheduleHide.emit()\"\n >\n @if (popover.editing) {\n <div class=\"flex items-center gap-1.5\">\n <label\n class=\"flex h-9 min-w-0 flex-1 items-center gap-2 rounded-md border border-input bg-background px-2 text-sm transition focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/30\"\n >\n <ng-icon\n class=\"shrink-0 text-muted-foreground\"\n name=\"lucideLink\"\n aria-hidden=\"true\"\n />\n <input\n class=\"min-w-0 flex-1 bg-transparent text-foreground outline-none placeholder:text-muted-foreground\"\n type=\"url\"\n aria-label=\"Edit link URL\"\n [value]=\"href()\"\n (input)=\"updateHref($event)\"\n />\n </label>\n <button\n qalmaBtn\n size=\"icon\"\n type=\"button\"\n [disabled]=\"!href().trim()\"\n (click)=\"save.emit(popover)\"\n title=\"Save link\"\n aria-label=\"Save link\"\n >\n <ng-icon name=\"lucideCheck\" aria-hidden=\"true\" />\n </button>\n <button\n qalmaBtn\n variant=\"outline\"\n size=\"icon\"\n type=\"button\"\n (click)=\"dismiss.emit()\"\n title=\"Cancel\"\n aria-label=\"Cancel\"\n >\n <ng-icon name=\"lucideX\" aria-hidden=\"true\" />\n </button>\n </div>\n } @else {\n <div class=\"flex items-center gap-1.5\">\n <a\n class=\"inline-flex h-9 min-w-0 flex-1 items-center gap-1.5 rounded-md border border-border bg-card px-2.5 text-accent transition-colors hover:bg-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n [href]=\"popover.href\"\n [target]=\"popover.target ?? '_blank'\"\n [rel]=\"popover.rel ?? 'noopener noreferrer'\"\n title=\"Open link\"\n >\n <span class=\"min-w-0 truncate font-medium\">{{\n popover.href\n }}</span>\n <ng-icon\n class=\"shrink-0 text-base\"\n name=\"lucideExternalLink\"\n aria-hidden=\"true\"\n />\n </a>\n <button\n qalmaBtn\n variant=\"outline\"\n size=\"icon\"\n type=\"button\"\n (click)=\"edit.emit(popover)\"\n title=\"Edit link\"\n aria-label=\"Edit link\"\n >\n <ng-icon name=\"lucidePencil\" aria-hidden=\"true\" />\n </button>\n <button\n qalmaBtn\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n class=\"text-destructive hover:bg-destructive/10 hover:text-destructive\"\n (click)=\"remove.emit(popover)\"\n title=\"Unlink\"\n aria-label=\"Unlink\"\n >\n <ng-icon name=\"lucideUnlink\" aria-hidden=\"true\" />\n </button>\n </div>\n }\n </div>\n }\n `,\n})\nexport class QalmaLinkPopover {\n readonly popover = input<LinkPopover | null>(null);\n readonly href = input.required<string>();\n\n readonly hrefChange = output<string>();\n readonly edit = output<LinkPopover>();\n readonly save = output<LinkPopover>();\n readonly remove = output<LinkPopover>();\n readonly dismiss = output<void>();\n readonly keepOpen = output<void>();\n readonly scheduleHide = output<void>();\n\n protected updateHref(event: Event): void {\n const target = event.target;\n\n if (target instanceof HTMLInputElement) {\n this.hrefChange.emit(target.value);\n }\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n input,\n output,\n} from '@angular/core';\nimport { QalmaToolbar } from '@qalma/editor';\n\nimport { QalmaContextualToolbarPlacement } from '@qalma/kit/headless';\n\n/**\n * Floating, selection-anchored toolbar container. It owns the hard parts — the\n * fixed-position `transform` from a {@link QalmaContextualToolbarPlacement}\n * (see `QalmaSelectionToolbarDirective`), preserving the editor selection on\n * pointer-down, and Escape-to-dismiss — and projects whatever controls you put\n * inside it. Nothing about the button set is baked in: compose\n * `<qalma-toolbar-button>` for commands and your own buttons for app actions\n * (opening a link editor, a color picker, an AI action…).\n *\n * The container's `mousedown` handler preserves the selection for every\n * projected control via event bubbling, so inner buttons don't each need to.\n *\n * ```html\n * <qalma-contextual-toolbar\n * [placement]=\"selection.placement()\"\n * (dismiss)=\"selection.hide()\"\n * >\n * <qalma-toolbar-button command=\"toggleBold\" icon=\"lucideBold\" label=\"Bold\" />\n * <qalma-toolbar-button command=\"toggleItalic\" icon=\"lucideItalic\" label=\"Italic\" />\n * <button type=\"button\" [class]=\"TOOLBAR_BUTTON_CLASS\" (click)=\"openLinkEditor()\">…</button>\n * </qalma-contextual-toolbar>\n * ```\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [QalmaToolbar],\n selector: 'qalma-contextual-toolbar',\n template: `\n @if (placement(); as placement) {\n <qalma-toolbar\n [label]=\"label()\"\n class=\"fixed left-0 top-0 z-30 flex items-center gap-0.5 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg will-change-transform\"\n [style.transform]=\"placement.transform\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown.escape)=\"dismissFromKeyboard($event)\"\n >\n <ng-content />\n </qalma-toolbar>\n }\n `,\n})\nexport class QalmaContextualToolbar {\n readonly placement = input<QalmaContextualToolbarPlacement | null>(null);\n /** Accessible name for the toolbar region. */\n readonly label = input('Selection formatting');\n readonly dismiss = output<void>();\n\n protected preserveSelection(event: MouseEvent): void {\n event.preventDefault();\n }\n\n protected dismissFromKeyboard(event: Event): void {\n event.preventDefault();\n this.dismiss.emit();\n }\n}\n","// @qalma/kit — Tailwind/shadcn-flavored UI for the Qalma editor.\n//\n// This entry point is the styled tier: components that pull `cva` + `@ng-icons`\n// and read the host's design tokens. It re-exports the entire dependency-free\n// `@qalma/kit/headless` surface (controllers, geometry, keyboard nav) so it\n// stays a superset — bring-your-own-design-system consumers can import the\n// leaner `@qalma/kit/headless` directly instead.\n//\n// The internal `QalmaButton` directive and `cn()` helper are intentionally NOT\n// exported: a host already has a button and a class-merge utility in its design\n// system. They remain private implementation details of the styled components.\nexport * from '@qalma/kit/headless';\n\n// Toolbar\nexport * from './lib/toolbar-button';\nexport * from './lib/toolbar-commands';\nexport * from './lib/toolbar-registry';\nexport * from './lib/toolbar-icons';\n\n// Editor surface components\nexport * from './lib/drag-handle';\nexport * from './lib/mention-menu';\nexport * from './lib/slash-command-menu';\nexport * from './lib/link-popover';\nexport * from './lib/contextual-toolbar';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"qalma-kit.mjs","sources":["../../../../libs/ui-kit/src/lib/toolbar-button.ts","../../../../libs/ui-kit/src/lib/toolbar-commands.ts","../../../../libs/ui-kit/src/lib/toolbar-registry.ts","../../../../libs/ui-kit/src/lib/toolbar-icons.ts","../../../../libs/ui-kit/src/lib/cn.ts","../../../../libs/ui-kit/src/lib/button.ts","../../../../libs/ui-kit/src/lib/drag-handle.ts","../../../../libs/ui-kit/src/lib/mention-menu.ts","../../../../libs/ui-kit/src/lib/slash-command-menu.ts","../../../../libs/ui-kit/src/lib/link-popover.ts","../../../../libs/ui-kit/src/lib/contextual-toolbar.ts","../../../../libs/ui-kit/src/index.ts","../../../../libs/ui-kit/src/qalma-kit.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { NgIcon } from '@ng-icons/core';\nimport { QalmaCommand } from '@qalma/editor';\n\n/**\n * Default styling for a toolbar command button. Icon-only, square, and driven\n * entirely by the host's shadcn-style design tokens (`text-muted-foreground`,\n * `bg-card`, `bg-secondary`, `bg-accent-subtle`…) so it themes with the\n * surrounding app.\n * The `qalma-command-active` class is toggled by the `QalmaCommand` directive\n * when the underlying command is active.\n */\nexport const TOOLBAR_BUTTON_CLASS =\n 'inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-border bg-card text-muted-foreground transition hover:border-accent/50 hover:bg-secondary hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45 [&.qalma-command-active]:border-accent/40 [&.qalma-command-active]:bg-accent-subtle [&.qalma-command-active]:text-accent';\n\n/**\n * Generic, declarative toolbar button for a single editor command.\n *\n * Renders a native `<button>` wired to the `QalmaCommand` directive (execute /\n * active / disabled / aria) with an `<ng-icon>`, so a whole toolbar becomes a\n * list of `<qalma-toolbar-button command icon label />` instead of the\n * six-line `<button qalmaCommand><ng-icon></button>` block repeated per\n * command. The host uses `display: contents` so the inner button participates\n * directly in the surrounding toolbar's flex layout.\n *\n * Icons resolve from the `NgIcon` provider scope of the surrounding component\n * (register them with `provideIcons({ … })` as usual).\n */\n@Component({\n selector: 'qalma-toolbar-button',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon, QalmaCommand],\n host: {\n class: 'contents',\n },\n template: `\n <button\n type=\"button\"\n [qalmaCommand]=\"command()\"\n [qalmaCommandValue]=\"value()\"\n [class]=\"buttonClass\"\n [title]=\"label()\"\n [attr.aria-label]=\"label()\"\n >\n <ng-icon [class]=\"iconClass()\" [name]=\"icon()\" aria-hidden=\"true\" />\n </button>\n `,\n})\nexport class QalmaToolbarButton {\n /** Command name to execute, e.g. `toggleBold`. */\n readonly command = input.required<string>();\n /** Optional command payload (forwarded to `qalmaCommandValue`). */\n readonly value = input<unknown>();\n /** Lucide (or any registered) icon name, e.g. `lucideBold`. */\n readonly icon = input.required<string>();\n /** Accessible name — used for both `title` and `aria-label`. */\n readonly label = input.required<string>();\n /** Optional icon-size class override (default: `text-[0.9rem]`). */\n readonly iconClass = input('text-[0.9rem]');\n\n protected readonly buttonClass = TOOLBAR_BUTTON_CLASS;\n}\n","import type { TemplateRef } from '@angular/core';\n\n/**\n * A single command button in a toolbar registry: which editor command to run,\n * which icon to show, and its accessible label. `value` is forwarded to the\n * command as its payload when present.\n */\nexport interface ToolbarCommandItem {\n readonly command: string;\n readonly icon: string;\n readonly label: string;\n readonly value?: unknown;\n}\n\n/**\n * An escape hatch for controls that are not a plain command button (color\n * pickers, upload buttons, a language `<select>`…). The consumer supplies an\n * `<ng-template>` and the toolbar renders it inline at this position.\n */\nexport interface ToolbarTemplateItem {\n readonly template: TemplateRef<unknown>;\n}\n\nexport type ToolbarItem = ToolbarCommandItem | ToolbarTemplateItem;\n\n/** One separator-delimited run of items. Empty groups render nothing. */\nexport type ToolbarGroup = readonly ToolbarItem[];\n\nexport function isToolbarCommandItem(\n item: ToolbarItem,\n): item is ToolbarCommandItem {\n return 'command' in item;\n}\n\n// ---------------------------------------------------------------------------\n// Default command fragments — the declarative source of truth for the standard\n// editor toolbar, reusable across consumers (playground, sandbox, downstream\n// apps). Compose them into `ToolbarGroup[]` and hand them to\n// `<qalma-toolbar-registry>`; interleave custom controls with `ToolbarTemplateItem`.\n// ---------------------------------------------------------------------------\n\nexport const QALMA_TOOLBAR_HEADINGS: readonly ToolbarCommandItem[] = [\n { command: 'setParagraph', icon: 'lucidePilcrow', label: 'Paragraph' },\n { command: 'toggleHeading1', icon: 'lucideHeading1', label: 'Heading 1' },\n { command: 'toggleHeading2', icon: 'lucideHeading2', label: 'Heading 2' },\n { command: 'toggleHeading3', icon: 'lucideHeading3', label: 'Heading 3' },\n];\n\nexport const QALMA_TOOLBAR_INLINE_MARKS: readonly ToolbarCommandItem[] = [\n { command: 'toggleBold', icon: 'lucideBold', label: 'Bold' },\n { command: 'toggleItalic', icon: 'lucideItalic', label: 'Italic' },\n { command: 'toggleUnderline', icon: 'lucideUnderline', label: 'Underline' },\n {\n command: 'toggleStrike',\n icon: 'lucideStrikethrough',\n label: 'Strikethrough',\n },\n { command: 'toggleInlineCode', icon: 'lucideCode', label: 'Inline code' },\n { command: 'toggleMonospace', icon: 'lucideLetterText', label: 'Monospace' },\n { command: 'toggleSubscript', icon: 'lucideSubscript', label: 'Subscript' },\n {\n command: 'toggleSuperscript',\n icon: 'lucideSuperscript',\n label: 'Superscript',\n },\n];\n\nexport const QALMA_TOOLBAR_ALIGN: readonly ToolbarCommandItem[] = [\n { command: 'setTextAlignLeft', icon: 'lucideAlignLeft', label: 'Align left' },\n {\n command: 'setTextAlignCenter',\n icon: 'lucideAlignCenter',\n label: 'Align center',\n },\n {\n command: 'setTextAlignRight',\n icon: 'lucideAlignRight',\n label: 'Align right',\n },\n {\n command: 'setTextAlignJustify',\n icon: 'lucideAlignJustify',\n label: 'Justify',\n },\n];\n\nexport const QALMA_TOOLBAR_LISTS: readonly ToolbarCommandItem[] = [\n { command: 'toggleBulletList', icon: 'lucideList', label: 'Bullet list' },\n {\n command: 'toggleOrderedList',\n icon: 'lucideListOrdered',\n label: 'Ordered list',\n },\n { command: 'toggleTaskList', icon: 'lucideListTodo', label: 'Task list' },\n { command: 'liftListItem', icon: 'lucideOutdent', label: 'Outdent' },\n { command: 'sinkListItem', icon: 'lucideIndent', label: 'Indent' },\n { command: 'toggleBlockquote', icon: 'lucideTextQuote', label: 'Blockquote' },\n { command: 'toggleCodeBlock', icon: 'lucideSquareCode', label: 'Code block' },\n];\n\n/** Always-available table entry point (inserting a new table). */\nexport const QALMA_TOOLBAR_TABLE_INSERT: ToolbarCommandItem = {\n command: 'insertTable',\n icon: 'lucideTable',\n label: 'Insert table',\n};\n\n/** Table editing commands — only meaningful while the selection is in a table. */\nexport const QALMA_TOOLBAR_TABLE_OPS: readonly ToolbarCommandItem[] = [\n {\n command: 'addRowAfter',\n icon: 'lucideBetweenHorizontalEnd',\n label: 'Add row',\n },\n {\n command: 'addColumnAfter',\n icon: 'lucideBetweenVerticalEnd',\n label: 'Add column',\n },\n { command: 'deleteRow', icon: 'lucideRows3', label: 'Delete row' },\n { command: 'deleteColumn', icon: 'lucideColumns3', label: 'Delete column' },\n {\n command: 'toggleHeaderRow',\n icon: 'lucideHeading',\n label: 'Toggle header row',\n },\n { command: 'deleteTable', icon: 'lucideTrash2', label: 'Delete table' },\n];\n\nexport const QALMA_TOOLBAR_HISTORY: readonly ToolbarCommandItem[] = [\n { command: 'undo', icon: 'lucideUndo2', label: 'Undo' },\n { command: 'redo', icon: 'lucideRedo2', label: 'Redo' },\n];\n\n/** Standalone command that usually sits alongside the color controls. */\nexport const QALMA_TOOLBAR_CLEAR_FORMATTING: ToolbarCommandItem = {\n command: 'clearFormatting',\n icon: 'lucideEraser',\n label: 'Clear formatting',\n};\n\n/** Standalone command that usually sits alongside the link/insert controls. */\nexport const QALMA_TOOLBAR_UNSET_LINK: ToolbarCommandItem = {\n command: 'unsetLink',\n icon: 'lucideUnlink',\n label: 'Unlink',\n};\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n TemplateRef,\n computed,\n input,\n} from '@angular/core';\n\nimport { QalmaToolbarButton } from './toolbar-button';\nimport {\n ToolbarCommandItem,\n ToolbarGroup,\n ToolbarItem,\n ToolbarTemplateItem,\n isToolbarCommandItem,\n} from './toolbar-commands';\n\n/** Vertical divider rendered between non-empty toolbar groups. */\nexport const TOOLBAR_SEPARATOR_CLASS =\n 'mx-0.5 h-5 w-px shrink-0 self-center bg-border';\n\n/**\n * Renders a declarative toolbar registry: an ordered list of groups, each a\n * list of command buttons and/or inline custom-control templates, with a\n * separator drawn between non-empty groups.\n *\n * Meant to sit inside the editor's `<qalma-toolbar>` (which owns the\n * `role=\"toolbar\"` semantics); the host uses `display: contents` so the\n * rendered buttons participate directly in that container's flex layout.\n *\n * ```html\n * <qalma-toolbar class=\"flex …\">\n * <ng-template #colors> … custom controls … </ng-template>\n * <qalma-toolbar-registry [groups]=\"[headings, marks, [{ template: colors }]]\" />\n * </qalma-toolbar>\n * ```\n */\n@Component({\n selector: 'qalma-toolbar-registry',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgTemplateOutlet, QalmaToolbarButton],\n host: {\n class: 'contents',\n },\n template: `\n @for (group of visibleGroups(); track $index; let first = $first) {\n @if (!first) {\n <span [class]=\"separatorClass()\" aria-hidden=\"true\"></span>\n }\n @for (item of group; track $index) {\n @if (asCommand(item); as command) {\n <qalma-toolbar-button\n [command]=\"command.command\"\n [value]=\"command.value\"\n [icon]=\"command.icon\"\n [label]=\"command.label\"\n />\n } @else {\n <ng-container [ngTemplateOutlet]=\"asTemplate(item)\" />\n }\n }\n }\n `,\n})\nexport class QalmaToolbarRegistry {\n readonly groups = input.required<readonly ToolbarGroup[]>();\n readonly separatorClass = input(TOOLBAR_SEPARATOR_CLASS);\n\n /** Drop empty groups so they neither render content nor a dangling separator. */\n protected readonly visibleGroups = computed(() =>\n this.groups().filter((group) => group.length > 0),\n );\n\n protected asCommand(item: ToolbarItem): ToolbarCommandItem | null {\n return isToolbarCommandItem(item) ? item : null;\n }\n\n protected asTemplate(item: ToolbarItem): TemplateRef<unknown> {\n return (item as ToolbarTemplateItem).template;\n }\n}\n","import { provideIcons } from '@ng-icons/core';\nimport {\n lucideAlignCenter,\n lucideAlignJustify,\n lucideAlignLeft,\n lucideAlignRight,\n lucideBetweenHorizontalEnd,\n lucideBetweenVerticalEnd,\n lucideBold,\n lucideCode,\n lucideColumns3,\n lucideEraser,\n lucideHeading,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideIndent,\n lucideItalic,\n lucideLetterText,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideOutdent,\n lucidePilcrow,\n lucideRedo2,\n lucideRows3,\n lucideSquareCode,\n lucideStrikethrough,\n lucideSubscript,\n lucideSuperscript,\n lucideTable,\n lucideTextQuote,\n lucideTrash2,\n lucideUnderline,\n lucideUndo2,\n lucideUnlink,\n} from '@ng-icons/lucide';\n\n/**\n * Registers the Lucide icons referenced by the default toolbar command\n * fragments (`QALMA_TOOLBAR_*`), so consumers can wire the standard toolbar\n * without re-declaring the icon set:\n *\n * ```ts\n * providers: [provideQalmaToolbarIcons()]\n * ```\n *\n * Add your own `provideIcons({ … })` alongside it for any custom controls\n * (color pickers, upload buttons…) that live outside the command registry.\n */\nexport function provideQalmaToolbarIcons() {\n return provideIcons({\n lucideAlignCenter,\n lucideAlignJustify,\n lucideAlignLeft,\n lucideAlignRight,\n lucideBetweenHorizontalEnd,\n lucideBetweenVerticalEnd,\n lucideBold,\n lucideCode,\n lucideColumns3,\n lucideEraser,\n lucideHeading,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideIndent,\n lucideItalic,\n lucideLetterText,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideOutdent,\n lucidePilcrow,\n lucideRedo2,\n lucideRows3,\n lucideSquareCode,\n lucideStrikethrough,\n lucideSubscript,\n lucideSuperscript,\n lucideTable,\n lucideTextQuote,\n lucideTrash2,\n lucideUnderline,\n lucideUndo2,\n lucideUnlink,\n });\n}\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { Directive, ElementRef, computed, inject, input } from '@angular/core';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from './cn';\n\nexport const buttonVariants = cva(\n 'inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 [&_ng-icon]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n outline:\n 'border border-border bg-card text-foreground hover:bg-secondary hover:text-secondary-foreground',\n ghost:\n 'text-foreground hover:bg-secondary hover:text-secondary-foreground',\n accent: 'bg-accent text-accent-foreground hover:bg-accent/90',\n link: 'text-accent underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 rounded-md px-3 text-xs',\n lg: 'h-11 rounded-md px-6 text-base',\n icon: 'h-9 w-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport type ButtonVariant = NonNullable<\n VariantProps<typeof buttonVariants>['variant']\n>;\nexport type ButtonSize = NonNullable<\n VariantProps<typeof buttonVariants>['size']\n>;\n\n/**\n * Headless-styled button directive so it composes onto native `<button>` and\n * `<a>` elements while reading from the host's Tailwind design tokens.\n */\n@Directive({\n selector: 'button[qalmaBtn], a[qalmaBtn]',\n host: {\n '[class]': 'computedClass()',\n },\n})\nexport class QalmaButton {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly initialClass =\n this.host.nativeElement.getAttribute('class') ?? '';\n\n readonly variant = input<ButtonVariant>('default');\n readonly size = input<ButtonSize>('default');\n\n protected readonly computedClass = computed(() =>\n cn(\n buttonVariants({ variant: this.variant(), size: this.size() }),\n this.initialClass,\n ),\n );\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { QalmaEditorController } from '@qalma/editor';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n lucideArrowDown,\n lucideArrowUp,\n lucideCopy,\n lucideGripVertical,\n lucideMousePointer2,\n lucideTrash2,\n} from '@ng-icons/lucide';\n\nimport {\n DismissibleOverlay,\n QalmaDragBlockHighlight,\n QalmaDragDropIndicator,\n QalmaDragHandleView,\n} from '@qalma/kit/headless';\n\nimport { QalmaButton } from './button';\n\nexport interface QalmaDragStart {\n event: PointerEvent;\n handle: QalmaDragHandleView;\n}\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon, QalmaButton],\n providers: [\n provideIcons({\n lucideArrowDown,\n lucideArrowUp,\n lucideCopy,\n lucideGripVertical,\n lucideMousePointer2,\n lucideTrash2,\n }),\n ],\n selector: 'qalma-drag-handle',\n template: `\n @if (draggedBlockHighlight(); as highlight) {\n <div\n data-qalma-dragging-block-highlight\n class=\"pointer-events-none fixed left-0 top-0 z-20 rounded-md border border-accent bg-accent-subtle/80 opacity-70 shadow-md will-change-transform\"\n [style.transform]=\"highlight.transform\"\n [style.width.px]=\"highlight.width\"\n [style.height.px]=\"highlight.height\"\n ></div>\n }\n\n @if (dropIndicator(); as indicator) {\n <div\n data-qalma-drag-drop-line\n class=\"pointer-events-none fixed left-0 top-0 z-40 h-0.5 rounded-full bg-accent shadow-md will-change-transform\"\n [style.transform]=\"indicator.transform\"\n [style.width.px]=\"indicator.width\"\n ></div>\n }\n\n @if (handle(); as handle) {\n <div\n data-qalma-drag-handle\n class=\"fixed left-0 top-0 z-30 flex items-start gap-1 will-change-transform\"\n tabindex=\"-1\"\n [style.transform]=\"handle.transform\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown.escape)=\"dismissFromKeyboard($event)\"\n >\n <button\n qalmaBtn\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n class=\"!h-[1.85rem] !w-[1.85rem] cursor-grab rounded-[0.4rem] border border-transparent bg-card/95 text-muted-foreground shadow-sm active:cursor-grabbing hover:border-border hover:bg-secondary hover:text-foreground\"\n [class.border-accent]=\"menuOpen()\"\n [class.text-accent]=\"menuOpen()\"\n (pointerdown)=\"startDrag($event, handle)\"\n (click)=\"toggleMenu()\"\n title=\"Block actions\"\n aria-label=\"Block actions\"\n [attr.aria-expanded]=\"menuOpen()\"\n >\n <ng-icon\n class=\"text-[0.9rem]\"\n name=\"lucideGripVertical\"\n aria-hidden=\"true\"\n />\n </button>\n\n @if (menuOpen()) {\n <div\n role=\"menu\"\n aria-label=\"Block actions\"\n class=\"w-44 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg\"\n >\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!canExecute('selectBlock', handle)\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('selectBlock', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideMousePointer2\" aria-hidden=\"true\" />\n Select block\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!handle.canMoveUp\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('moveBlockUp', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideArrowUp\" aria-hidden=\"true\" />\n Move up\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!handle.canMoveDown\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('moveBlockDown', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideArrowDown\" aria-hidden=\"true\" />\n Move down\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-foreground transition hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!canExecute('duplicateBlock', handle)\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('duplicateBlock', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideCopy\" aria-hidden=\"true\" />\n Duplicate\n </button>\n <button\n type=\"button\"\n class=\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs font-medium text-destructive transition hover:bg-destructive/10 disabled:cursor-not-allowed disabled:opacity-45\"\n [disabled]=\"!canExecute('deleteBlock', handle)\"\n (mousedown)=\"preserveSelection($event)\"\n (click)=\"execute('deleteBlock', handle)\"\n role=\"menuitem\"\n >\n <ng-icon name=\"lucideTrash2\" aria-hidden=\"true\" />\n Delete\n </button>\n </div>\n }\n </div>\n }\n `,\n})\nexport class QalmaDragHandle {\n readonly editor = input.required<QalmaEditorController>();\n readonly handle = input<QalmaDragHandleView | null>(null);\n readonly dropIndicator = input<QalmaDragDropIndicator | null>(null);\n readonly draggedBlockHighlight = input<QalmaDragBlockHighlight | null>(\n null,\n );\n readonly dismiss = output<void>();\n readonly dragStart = output<QalmaDragStart>();\n\n protected readonly menuOpen = signal(false);\n\n constructor() {\n // Close the block-actions menu on an outside pointerdown or Escape. A click\n // on the handle button or the menu itself (both under `[data-qalma-drag-handle]`)\n // is treated as inside, so it doesn't self-dismiss. Connected for the\n // component's lifetime; the callback is a no-op while the menu is closed.\n new DismissibleOverlay({\n isInside: (target) =>\n target instanceof Element &&\n !!target.closest('[data-qalma-drag-handle]'),\n onDismiss: () => this.menuOpen.set(false),\n }).connect(inject(DestroyRef));\n }\n\n protected toggleMenu(): void {\n this.menuOpen.update((open) => !open);\n }\n\n protected startDrag(\n event: PointerEvent,\n handle: QalmaDragHandleView,\n ): void {\n this.menuOpen.set(false);\n this.dragStart.emit({ event, handle });\n }\n\n protected canExecute(\n command: string,\n handle: QalmaDragHandleView,\n ): boolean {\n return this.editor().canExecute(command, handle.target);\n }\n\n protected execute(command: string, handle: QalmaDragHandleView): void {\n if (this.editor().execute(command, handle.target)) {\n this.dismissHandle();\n }\n }\n\n protected preserveSelection(event: MouseEvent): void {\n event.preventDefault();\n }\n\n protected dismissFromKeyboard(event: Event): void {\n event.preventDefault();\n this.dismissHandle();\n }\n\n protected dismissHandle(): void {\n this.menuOpen.set(false);\n this.dismiss.emit();\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\n\nimport { QalmaSuggestionMenu } from '@qalma/kit/headless';\n\nexport interface QalmaMentionOption {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n}\n\n/**\n * Caret-anchored mention suggestion menu: an avatar-initial list with a loading\n * state. Positioning, keyboard handling and active highlighting come from\n * {@link QalmaSuggestionMenu}; feed it a `placement` (see `flipAbovePlacement`)\n * and the filtered `suggestions`.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'qalma-mention-menu',\n template: `\n @if (placement(); as placement) {\n <div\n role=\"listbox\"\n aria-label=\"Mention suggestions\"\n class=\"fixed z-20 w-[min(280px,calc(100vw-24px))] overflow-hidden rounded-md border border-border bg-popover p-1 text-sm text-popover-foreground shadow-lg outline-none\"\n [style.left.px]=\"placement.left\"\n [style.top.px]=\"placement.top\"\n [style.bottom.px]=\"placement.bottom\"\n [style.max-height.px]=\"placement.maxHeight\"\n >\n @if (loading()) {\n <div\n class=\"flex items-center gap-2 px-2 py-2 text-sm text-muted-foreground\"\n >\n <span\n class=\"size-7 animate-pulse rounded-sm border border-border bg-secondary\"\n aria-hidden=\"true\"\n ></span>\n <span>Loading…</span>\n </div>\n } @else {\n <div class=\"max-h-full overflow-y-auto\">\n @for (\n option of suggestions();\n track option.id;\n let index = $index\n ) {\n <button\n type=\"button\"\n role=\"option\"\n [attr.data-suggestion-index]=\"index\"\n class=\"group grid h-12 w-full min-w-0 cursor-pointer grid-cols-[1.75rem_minmax(0,1fr)] items-center gap-2 rounded-sm px-2 text-left transition-colors hover:bg-accent-subtle hover:text-foreground focus:bg-accent-subtle focus:text-foreground focus:outline-none\"\n [class.bg-accent-subtle]=\"index === activeIndex()\"\n [class.text-foreground]=\"index === activeIndex()\"\n [attr.aria-selected]=\"index === activeIndex()\"\n [attr.tabindex]=\"index === activeIndex() ? 0 : -1\"\n (mouseenter)=\"activate.emit(index)\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown)=\"handleOptionKeydown($event, option, index)\"\n (click)=\"pick.emit(option)\"\n >\n <span\n class=\"flex size-7 items-center justify-center rounded-sm border border-border bg-card text-xs font-semibold text-foreground\"\n [class.border-accent]=\"index === activeIndex()\"\n [class.bg-background]=\"index === activeIndex()\"\n [class.text-accent]=\"index === activeIndex()\"\n aria-hidden=\"true\"\n >\n {{ option.label.slice(0, 1) }}\n </span>\n <span class=\"min-w-0\">\n <span class=\"block truncate font-medium leading-5\">{{\n option.label\n }}</span>\n @if (index === activeIndex()) {\n <span\n class=\"block truncate text-xs leading-4 text-foreground\"\n >\n {{ option.description }}\n </span>\n } @else {\n <span\n class=\"block truncate text-xs leading-4 text-muted-foreground group-hover:text-foreground group-focus:text-foreground\"\n >\n {{ option.description }}\n </span>\n }\n </span>\n </button>\n }\n </div>\n }\n </div>\n }\n `,\n})\nexport class QalmaMentionMenu extends QalmaSuggestionMenu<QalmaMentionOption> {\n readonly suggestions = input<readonly QalmaMentionOption[]>([]);\n readonly loading = input(false);\n\n protected readonly optionList = this.suggestions;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n effect,\n input,\n} from '@angular/core';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n lucideCode,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideMinus,\n lucidePilcrow,\n lucideSquareCode,\n lucideTable,\n lucideTextQuote,\n} from '@ng-icons/lucide';\nimport { QalmaCommandValue } from '@qalma/editor';\n\nimport { QalmaSuggestionMenu } from '@qalma/kit/headless';\n\nexport interface QalmaSlashCommandOption {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n readonly icon: string;\n readonly shortcut: string;\n /** Editor command to run when the option is picked. */\n readonly command: string;\n readonly value?: QalmaCommandValue;\n readonly placement?: 'block' | 'inline';\n /** Extra terms the consumer can match against when filtering. */\n readonly keywords: readonly string[];\n}\n\n/**\n * Caret-anchored slash-command menu: an icon + shortcut list with a \"Commands\"\n * header and an Escape hint footer, scrolling the active option into view.\n * Positioning, keyboard handling and active highlighting come from\n * {@link QalmaSuggestionMenu}; feed it a `placement` (see `flipAbovePlacement`)\n * and the filtered `options`. Ships the default block-command icon set.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon],\n providers: [\n provideIcons({\n lucideCode,\n lucideHeading1,\n lucideHeading2,\n lucideHeading3,\n lucideList,\n lucideListOrdered,\n lucideListTodo,\n lucideMinus,\n lucidePilcrow,\n lucideSquareCode,\n lucideTable,\n lucideTextQuote,\n }),\n ],\n selector: 'qalma-slash-command-menu',\n template: `\n @if (placement(); as placement) {\n <div\n role=\"listbox\"\n aria-label=\"Slash command suggestions\"\n class=\"fixed z-20 flex w-[min(320px,calc(100vw-24px))] flex-col overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg outline-none\"\n [style.left.px]=\"placement.left\"\n [style.top.px]=\"placement.top\"\n [style.bottom.px]=\"placement.bottom\"\n [style.max-height.px]=\"placement.maxHeight\"\n >\n <div\n class=\"shrink-0 px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\"\n >\n Commands\n </div>\n <div data-suggestion-options class=\"min-h-0 flex-1 overflow-y-auto\">\n @for (option of options(); track option.id; let index = $index) {\n <button\n type=\"button\"\n role=\"option\"\n [attr.data-suggestion-index]=\"index\"\n class=\"group grid h-11 w-full min-w-0 cursor-pointer grid-cols-[1.75rem_minmax(0,1fr)_auto] items-center gap-2 rounded-sm px-2 text-left text-sm transition-colors hover:bg-accent-subtle hover:text-foreground focus:bg-accent-subtle focus:text-foreground focus:outline-none\"\n [class.bg-accent-subtle]=\"index === activeIndex()\"\n [class.text-foreground]=\"index === activeIndex()\"\n [attr.aria-selected]=\"index === activeIndex()\"\n [attr.tabindex]=\"index === activeIndex() ? 0 : -1\"\n (mouseenter)=\"activate.emit(index)\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown)=\"handleOptionKeydown($event, option, index)\"\n (click)=\"pick.emit(option)\"\n >\n <span\n class=\"flex size-7 items-center justify-center rounded-sm border border-border bg-card text-[14px] text-foreground\"\n [class.border-accent]=\"index === activeIndex()\"\n [class.bg-background]=\"index === activeIndex()\"\n [class.text-accent]=\"index === activeIndex()\"\n >\n <ng-icon [name]=\"option.icon\" aria-hidden=\"true\" />\n </span>\n <span class=\"min-w-0\">\n <span class=\"block truncate font-medium leading-5\">{{\n option.label\n }}</span>\n @if (index === activeIndex()) {\n <span\n class=\"block truncate text-xs leading-4 text-foreground\"\n >\n {{ option.description }}\n </span>\n } @else {\n <span\n class=\"block truncate text-xs leading-4 text-muted-foreground group-hover:text-foreground group-focus:text-foreground\"\n >\n {{ option.description }}\n </span>\n }\n </span>\n <kbd\n class=\"rounded-sm border border-border bg-card px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground\"\n [class.border-accent]=\"index === activeIndex()\"\n [class.bg-background]=\"index === activeIndex()\"\n [class.text-accent]=\"index === activeIndex()\"\n >\n {{ option.shortcut }}\n </kbd>\n </button>\n }\n </div>\n <div\n class=\"mt-1 flex h-8 shrink-0 items-center justify-between border-t border-border px-2 text-[11px] text-muted-foreground\"\n >\n <span>Close menu</span>\n <kbd\n class=\"rounded-sm border border-border bg-card px-1.5 py-0.5 font-mono\"\n >esc</kbd\n >\n </div>\n </div>\n }\n `,\n})\nexport class QalmaSlashCommandMenu extends QalmaSuggestionMenu<QalmaSlashCommandOption> {\n readonly options = input<readonly QalmaSlashCommandOption[]>([]);\n\n protected readonly optionList = this.options;\n\n constructor() {\n super();\n\n effect(() => {\n const activeIndex = this.activeIndex();\n\n this.options();\n queueMicrotask(() => this.scrollOptionIntoView(activeIndex));\n });\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n input,\n output,\n} from '@angular/core';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n lucideCheck,\n lucideExternalLink,\n lucideLink,\n lucidePencil,\n lucideUnlink,\n lucideX,\n} from '@ng-icons/lucide';\n\nimport { LinkPopover } from '@qalma/kit/headless';\n\nimport { QalmaButton } from './button';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgIcon, QalmaButton],\n providers: [\n provideIcons({\n lucideCheck,\n lucideExternalLink,\n lucideLink,\n lucidePencil,\n lucideUnlink,\n lucideX,\n }),\n ],\n selector: 'qalma-link-popover',\n template: `\n @if (popover(); as popover) {\n <div\n data-qalma-link-popover\n role=\"dialog\"\n aria-label=\"Link preview\"\n class=\"fixed z-20 w-[min(360px,calc(100vw-32px))] rounded-md border border-border bg-popover p-1.5 text-sm text-popover-foreground shadow-lg outline-none\"\n [style.left.px]=\"popover.left\"\n [style.top.px]=\"popover.top\"\n (mouseenter)=\"keepOpen.emit()\"\n (mouseleave)=\"scheduleHide.emit()\"\n (focusin)=\"keepOpen.emit()\"\n (focusout)=\"scheduleHide.emit()\"\n >\n @if (popover.editing) {\n <div class=\"flex items-center gap-1.5\">\n <label\n class=\"flex h-9 min-w-0 flex-1 items-center gap-2 rounded-md border border-input bg-background px-2 text-sm transition focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/30\"\n >\n <ng-icon\n class=\"shrink-0 text-muted-foreground\"\n name=\"lucideLink\"\n aria-hidden=\"true\"\n />\n <input\n class=\"min-w-0 flex-1 bg-transparent text-foreground outline-none placeholder:text-muted-foreground\"\n type=\"url\"\n aria-label=\"Edit link URL\"\n [value]=\"href()\"\n (input)=\"updateHref($event)\"\n />\n </label>\n <button\n qalmaBtn\n size=\"icon\"\n type=\"button\"\n [disabled]=\"!href().trim()\"\n (click)=\"save.emit(popover)\"\n title=\"Save link\"\n aria-label=\"Save link\"\n >\n <ng-icon name=\"lucideCheck\" aria-hidden=\"true\" />\n </button>\n <button\n qalmaBtn\n variant=\"outline\"\n size=\"icon\"\n type=\"button\"\n (click)=\"dismiss.emit()\"\n title=\"Cancel\"\n aria-label=\"Cancel\"\n >\n <ng-icon name=\"lucideX\" aria-hidden=\"true\" />\n </button>\n </div>\n } @else {\n <div class=\"flex items-center gap-1.5\">\n <a\n class=\"inline-flex h-9 min-w-0 flex-1 items-center gap-1.5 rounded-md border border-border bg-card px-2.5 text-accent transition-colors hover:bg-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n [href]=\"popover.href\"\n [target]=\"popover.target ?? '_blank'\"\n [rel]=\"popover.rel ?? 'noopener noreferrer'\"\n title=\"Open link\"\n >\n <span class=\"min-w-0 truncate font-medium\">{{\n popover.href\n }}</span>\n <ng-icon\n class=\"shrink-0 text-base\"\n name=\"lucideExternalLink\"\n aria-hidden=\"true\"\n />\n </a>\n <button\n qalmaBtn\n variant=\"outline\"\n size=\"icon\"\n type=\"button\"\n (click)=\"edit.emit(popover)\"\n title=\"Edit link\"\n aria-label=\"Edit link\"\n >\n <ng-icon name=\"lucidePencil\" aria-hidden=\"true\" />\n </button>\n <button\n qalmaBtn\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n class=\"text-destructive hover:bg-destructive/10 hover:text-destructive\"\n (click)=\"remove.emit(popover)\"\n title=\"Unlink\"\n aria-label=\"Unlink\"\n >\n <ng-icon name=\"lucideUnlink\" aria-hidden=\"true\" />\n </button>\n </div>\n }\n </div>\n }\n `,\n})\nexport class QalmaLinkPopover {\n readonly popover = input<LinkPopover | null>(null);\n readonly href = input.required<string>();\n\n readonly hrefChange = output<string>();\n readonly edit = output<LinkPopover>();\n readonly save = output<LinkPopover>();\n readonly remove = output<LinkPopover>();\n readonly dismiss = output<void>();\n readonly keepOpen = output<void>();\n readonly scheduleHide = output<void>();\n\n protected updateHref(event: Event): void {\n const target = event.target;\n\n if (target instanceof HTMLInputElement) {\n this.hrefChange.emit(target.value);\n }\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n input,\n output,\n} from '@angular/core';\nimport { QalmaToolbar } from '@qalma/editor';\n\nimport { QalmaContextualToolbarPlacement } from '@qalma/kit/headless';\n\n/**\n * Floating, selection-anchored toolbar container. It owns the hard parts — the\n * fixed-position `transform` from a {@link QalmaContextualToolbarPlacement}\n * (see `QalmaSelectionToolbarDirective`), preserving the editor selection on\n * pointer-down, and Escape-to-dismiss — and projects whatever controls you put\n * inside it. Nothing about the button set is baked in: compose\n * `<qalma-toolbar-button>` for commands and your own buttons for app actions\n * (opening a link editor, a color picker, an AI action…).\n *\n * The container's `mousedown` handler preserves the selection for every\n * projected control via event bubbling, so inner buttons don't each need to.\n *\n * ```html\n * <qalma-contextual-toolbar\n * [placement]=\"selection.placement()\"\n * (dismiss)=\"selection.hide()\"\n * >\n * <qalma-toolbar-button command=\"toggleBold\" icon=\"lucideBold\" label=\"Bold\" />\n * <qalma-toolbar-button command=\"toggleItalic\" icon=\"lucideItalic\" label=\"Italic\" />\n * <button type=\"button\" [class]=\"TOOLBAR_BUTTON_CLASS\" (click)=\"openLinkEditor()\">…</button>\n * </qalma-contextual-toolbar>\n * ```\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [QalmaToolbar],\n selector: 'qalma-contextual-toolbar',\n template: `\n @if (placement(); as placement) {\n <qalma-toolbar\n [label]=\"label()\"\n class=\"fixed left-0 top-0 z-30 flex items-center gap-0.5 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg will-change-transform\"\n [style.transform]=\"placement.transform\"\n (mousedown)=\"preserveSelection($event)\"\n (keydown.escape)=\"dismissFromKeyboard($event)\"\n >\n <ng-content />\n </qalma-toolbar>\n }\n `,\n})\nexport class QalmaContextualToolbar {\n readonly placement = input<QalmaContextualToolbarPlacement | null>(null);\n /** Accessible name for the toolbar region. */\n readonly label = input('Selection formatting');\n readonly dismiss = output<void>();\n\n protected preserveSelection(event: MouseEvent): void {\n event.preventDefault();\n }\n\n protected dismissFromKeyboard(event: Event): void {\n event.preventDefault();\n this.dismiss.emit();\n }\n}\n","// @qalma/kit — Tailwind/shadcn-flavored UI for the Qalma editor.\n//\n// This entry point is the styled tier: components that pull `cva` + `@ng-icons`\n// and read the host's design tokens. It re-exports the entire dependency-free\n// `@qalma/kit/headless` surface (controllers, geometry, keyboard nav) so it\n// stays a superset — bring-your-own-design-system consumers can import the\n// leaner `@qalma/kit/headless` directly instead.\n//\n// The internal `QalmaButton` directive and `cn()` helper are intentionally NOT\n// exported: a host already has a button and a class-merge utility in its design\n// system. They remain private implementation details of the styled components.\nexport * from '@qalma/kit/headless';\n\n// Toolbar\nexport * from './lib/toolbar-button';\nexport * from './lib/toolbar-commands';\nexport * from './lib/toolbar-registry';\nexport * from './lib/toolbar-icons';\n\n// Editor surface components\nexport * from './lib/drag-handle';\nexport * from './lib/mention-menu';\nexport * from './lib/slash-command-menu';\nexport * from './lib/link-popover';\nexport * from './lib/contextual-toolbar';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;AAIA;;;;;;;AAOG;AACI,MAAM,oBAAoB,GAC/B;AAEF;;;;;;;;;;;;AAYG;MAqBU,kBAAkB,CAAA;;AAEpB,IAAA,OAAO,GAAG,KAAK,CAAC,QAAQ,6EAAU;;IAElC,KAAK,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAW;;AAExB,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,0EAAU;;AAE/B,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,2EAAU;;AAEhC,IAAA,SAAS,GAAG,KAAK,CAAC,eAAe,gFAAC;IAExB,WAAW,GAAG,oBAAoB;wGAZ1C,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,UAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAbnB;;;;;;;;;;;GAWT,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAfS,MAAM,6GAAE,YAAY,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,cAAA,EAAA,mBAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAiBnB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBApB9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,sBAAsB;oBAChC,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;AAC/B,oBAAA,IAAI,EAAE;AACJ,wBAAA,KAAK,EAAE,UAAU;AAClB,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;AAWT,EAAA,CAAA;AACF,iBAAA;;;ACnBK,SAAU,oBAAoB,CAClC,IAAiB,EAAA;IAEjB,OAAO,SAAS,IAAI,IAAI;AAC1B;AAEA;AACA;AACA;AACA;AACA;AACA;AAEO,MAAM,sBAAsB,GAAkC;IACnE,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE;IACtE,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,EAAE;IACzE,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,EAAE;IACzE,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,EAAE;;AAGpE,MAAM,0BAA0B,GAAkC;IACvE,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE;IAC5D,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE;IAClE,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,EAAE;AAC3E,IAAA;AACE,QAAA,OAAO,EAAE,cAAc;AACvB,QAAA,IAAI,EAAE,qBAAqB;AAC3B,QAAA,KAAK,EAAE,eAAe;AACvB,KAAA;IACD,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE;IACzE,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,WAAW,EAAE;IAC5E,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,EAAE;AAC3E,IAAA;AACE,QAAA,OAAO,EAAE,mBAAmB;AAC5B,QAAA,IAAI,EAAE,mBAAmB;AACzB,QAAA,KAAK,EAAE,aAAa;AACrB,KAAA;;AAGI,MAAM,mBAAmB,GAAkC;IAChE,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,EAAE;AAC7E,IAAA;AACE,QAAA,OAAO,EAAE,oBAAoB;AAC7B,QAAA,IAAI,EAAE,mBAAmB;AACzB,QAAA,KAAK,EAAE,cAAc;AACtB,KAAA;AACD,IAAA;AACE,QAAA,OAAO,EAAE,mBAAmB;AAC5B,QAAA,IAAI,EAAE,kBAAkB;AACxB,QAAA,KAAK,EAAE,aAAa;AACrB,KAAA;AACD,IAAA;AACE,QAAA,OAAO,EAAE,qBAAqB;AAC9B,QAAA,IAAI,EAAE,oBAAoB;AAC1B,QAAA,KAAK,EAAE,SAAS;AACjB,KAAA;;AAGI,MAAM,mBAAmB,GAAkC;IAChE,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE;AACzE,IAAA;AACE,QAAA,OAAO,EAAE,mBAAmB;AAC5B,QAAA,IAAI,EAAE,mBAAmB;AACzB,QAAA,KAAK,EAAE,cAAc;AACtB,KAAA;IACD,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,EAAE;IACzE,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE;IACpE,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE;IAClE,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,EAAE;IAC7E,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,EAAE;;AAG/E;AACO,MAAM,0BAA0B,GAAuB;AAC5D,IAAA,OAAO,EAAE,aAAa;AACtB,IAAA,IAAI,EAAE,aAAa;AACnB,IAAA,KAAK,EAAE,cAAc;;AAGvB;AACO,MAAM,uBAAuB,GAAkC;AACpE,IAAA;AACE,QAAA,OAAO,EAAE,aAAa;AACtB,QAAA,IAAI,EAAE,4BAA4B;AAClC,QAAA,KAAK,EAAE,SAAS;AACjB,KAAA;AACD,IAAA;AACE,QAAA,OAAO,EAAE,gBAAgB;AACzB,QAAA,IAAI,EAAE,0BAA0B;AAChC,QAAA,KAAK,EAAE,YAAY;AACpB,KAAA;IACD,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE;IAClE,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,EAAE;AAC3E,IAAA;AACE,QAAA,OAAO,EAAE,iBAAiB;AAC1B,QAAA,IAAI,EAAE,eAAe;AACrB,QAAA,KAAK,EAAE,mBAAmB;AAC3B,KAAA;IACD,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;;AAGlE,MAAM,qBAAqB,GAAkC;IAClE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE;IACvD,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE;;AAGzD;AACO,MAAM,8BAA8B,GAAuB;AAChE,IAAA,OAAO,EAAE,iBAAiB;AAC1B,IAAA,IAAI,EAAE,cAAc;AACpB,IAAA,KAAK,EAAE,kBAAkB;;AAG3B;AACO,MAAM,wBAAwB,GAAuB;AAC1D,IAAA,OAAO,EAAE,WAAW;AACpB,IAAA,IAAI,EAAE,cAAc;AACpB,IAAA,KAAK,EAAE,QAAQ;;;AC/HjB;AACO,MAAM,uBAAuB,GAClC;AAEF;;;;;;;;;;;;;;;AAeG;MA4BU,oBAAoB,CAAA;AACtB,IAAA,MAAM,GAAG,KAAK,CAAC,QAAQ,4EAA2B;AAClD,IAAA,cAAc,GAAG,KAAK,CAAC,uBAAuB,qFAAC;;IAGrC,aAAa,GAAG,QAAQ,CAAC,MAC1C,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,eAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAClD;AAES,IAAA,SAAS,CAAC,IAAiB,EAAA;AACnC,QAAA,OAAO,oBAAoB,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IACjD;AAEU,IAAA,UAAU,CAAC,IAAiB,EAAA;QACpC,OAAQ,IAA4B,CAAC,QAAQ;IAC/C;wGAfW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,UAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApBrB;;;;;;;;;;;;;;;;;;GAkBT,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAtBS,gBAAgB,oJAAE,kBAAkB,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,EAAA,MAAA,EAAA,OAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAwBnC,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBA3BhC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,wBAAwB;oBAClC,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,OAAO,EAAE,CAAC,gBAAgB,EAAE,kBAAkB,CAAC;AAC/C,oBAAA,IAAI,EAAE;AACJ,wBAAA,KAAK,EAAE,UAAU;AAClB,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;AAkBT,EAAA,CAAA;AACF,iBAAA;;;AC1BD;;;;;;;;;;;AAWG;SACa,wBAAwB,GAAA;AACtC,IAAA,OAAO,YAAY,CAAC;QAClB,iBAAiB;QACjB,kBAAkB;QAClB,eAAe;QACf,gBAAgB;QAChB,0BAA0B;QAC1B,wBAAwB;QACxB,UAAU;QACV,UAAU;QACV,cAAc;QACd,YAAY;QACZ,aAAa;QACb,cAAc;QACd,cAAc;QACd,cAAc;QACd,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,UAAU;QACV,iBAAiB;QACjB,cAAc;QACd,aAAa;QACb,aAAa;QACb,WAAW;QACX,WAAW;QACX,gBAAgB;QAChB,mBAAmB;QACnB,eAAe;QACf,iBAAiB;QACjB,WAAW;QACX,eAAe;QACf,YAAY;QACZ,eAAe;QACf,WAAW;QACX,YAAY;AACb,KAAA,CAAC;AACJ;;ACpFM,SAAU,EAAE,CAAC,GAAG,MAAoB,EAAA;AACxC,IAAA,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC9B;;ACAO,MAAM,cAAc,GAAG,GAAG,CAC/B,gVAAgV,EAChV;AACE,IAAA,QAAQ,EAAE;AACR,QAAA,OAAO,EAAE;AACP,YAAA,OAAO,EAAE,wDAAwD;AACjE,YAAA,SAAS,EACP,8DAA8D;AAChE,YAAA,OAAO,EACL,iGAAiG;AACnG,YAAA,KAAK,EACH,oEAAoE;AACtE,YAAA,MAAM,EAAE,qDAAqD;AAC7D,YAAA,IAAI,EAAE,gDAAgD;AACvD,SAAA;AACD,QAAA,IAAI,EAAE;AACJ,YAAA,OAAO,EAAE,eAAe;AACxB,YAAA,EAAE,EAAE,6BAA6B;AACjC,YAAA,EAAE,EAAE,gCAAgC;AACpC,YAAA,IAAI,EAAE,SAAS;AAChB,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,OAAO,EAAE,SAAS;AAClB,QAAA,IAAI,EAAE,SAAS;AAChB,KAAA;AACF,CAAA,CACF;AASD;;;AAGG;MAOU,WAAW,CAAA;AACL,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;AAClD,IAAA,YAAY,GAC3B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE;AAE5C,IAAA,OAAO,GAAG,KAAK,CAAgB,SAAS,8EAAC;AACzC,IAAA,IAAI,GAAG,KAAK,CAAa,SAAS,2EAAC;AAEzB,IAAA,aAAa,GAAG,QAAQ,CAAC,MAC1C,EAAE,CACA,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAC9D,IAAI,CAAC,YAAY,CAClB,oFACF;wGAbU,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAX,WAAW,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAAX,WAAW,EAAA,UAAA,EAAA,CAAA;kBANvB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,+BAA+B;AACzC,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE,iBAAiB;AAC7B,qBAAA;AACF,iBAAA;;;MCmHY,eAAe,CAAA;AACjB,IAAA,MAAM,GAAG,KAAK,CAAC,QAAQ,4EAAyB;AAChD,IAAA,MAAM,GAAG,KAAK,CAA6B,IAAI,6EAAC;AAChD,IAAA,aAAa,GAAG,KAAK,CAAgC,IAAI,oFAAC;AAC1D,IAAA,qBAAqB,GAAG,KAAK,CACpC,IAAI,4FACL;IACQ,OAAO,GAAG,MAAM,EAAQ;IACxB,SAAS,GAAG,MAAM,EAAkB;AAE1B,IAAA,QAAQ,GAAG,MAAM,CAAC,KAAK,+EAAC;AAE3C,IAAA,WAAA,GAAA;;;;;AAKE,QAAA,IAAI,kBAAkB,CAAC;YACrB,QAAQ,EAAE,CAAC,MAAM,KACf,MAAM,YAAY,OAAO;AACzB,gBAAA,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC;YAC9C,SAAS,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;SAC1C,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC;IAEU,UAAU,GAAA;AAClB,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC;IACvC;IAEU,SAAS,CACjB,KAAmB,EACnB,MAA2B,EAAA;AAE3B,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACxC;IAEU,UAAU,CAClB,OAAe,EACf,MAA2B,EAAA;AAE3B,QAAA,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;IACzD;IAEU,OAAO,CAAC,OAAe,EAAE,MAA2B,EAAA;AAC5D,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE;YACjD,IAAI,CAAC,aAAa,EAAE;QACtB;IACF;AAEU,IAAA,iBAAiB,CAAC,KAAiB,EAAA;QAC3C,KAAK,CAAC,cAAc,EAAE;IACxB;AAEU,IAAA,mBAAmB,CAAC,KAAY,EAAA;QACxC,KAAK,CAAC,cAAc,EAAE;QACtB,IAAI,CAAC,aAAa,EAAE;IACtB;IAEU,aAAa,GAAA;AACrB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AACxB,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;IACrB;wGA9DW,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,qBAAA,EAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,UAAA,EAAA,uBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,SAAA,EAhIf;AACT,YAAA,YAAY,CAAC;gBACX,eAAe;gBACf,aAAa;gBACb,UAAU;gBACV,kBAAkB;gBAClB,mBAAmB;gBACnB,YAAY;aACb,CAAC;SACH,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAES;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmHT,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA/HS,MAAM,6GAAE,WAAW,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAiIlB,eAAe,EAAA,UAAA,EAAA,CAAA;kBAnI3B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;AAC9B,oBAAA,SAAS,EAAE;AACT,wBAAA,YAAY,CAAC;4BACX,eAAe;4BACf,aAAa;4BACb,UAAU;4BACV,kBAAkB;4BAClB,mBAAmB;4BACnB,YAAY;yBACb,CAAC;AACH,qBAAA;AACD,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmHT,EAAA,CAAA;AACF,iBAAA;;;AC1JD;;;;;AAKG;AAiFG,MAAO,gBAAiB,SAAQ,mBAAuC,CAAA;AAClE,IAAA,WAAW,GAAG,KAAK,CAAgC,EAAE,kFAAC;AACtD,IAAA,OAAO,GAAG,KAAK,CAAC,KAAK,8EAAC;AAEZ,IAAA,UAAU,GAAG,IAAI,CAAC,WAAW;wGAJrC,gBAAgB,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,gBAAgB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA7EjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2ET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAEU,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAhF5B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2ET,EAAA,CAAA;AACF,iBAAA;;;ACxDD;;;;;;AAMG;AAuGG,MAAO,qBAAsB,SAAQ,mBAA4C,CAAA;AAC5E,IAAA,OAAO,GAAG,KAAK,CAAqC,EAAE,8EAAC;AAE7C,IAAA,UAAU,GAAG,IAAI,CAAC,OAAO;AAE5C,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QAEP,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE;YAEtC,IAAI,CAAC,OAAO,EAAE;YACd,cAAc,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;AAC9D,QAAA,CAAC,CAAC;IACJ;wGAdW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAnGrB;AACT,YAAA,YAAY,CAAC;gBACX,UAAU;gBACV,cAAc;gBACd,cAAc;gBACd,cAAc;gBACd,UAAU;gBACV,iBAAiB;gBACjB,cAAc;gBACd,WAAW;gBACX,aAAa;gBACb,gBAAgB;gBAChB,WAAW;gBACX,eAAe;aAChB,CAAC;SACH,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAES;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAlGS,MAAM,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,aAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAoGL,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAtGjC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,OAAO,EAAE,CAAC,MAAM,CAAC;AACjB,oBAAA,SAAS,EAAE;AACT,wBAAA,YAAY,CAAC;4BACX,UAAU;4BACV,cAAc;4BACd,cAAc;4BACd,cAAc;4BACd,UAAU;4BACV,iBAAiB;4BACjB,cAAc;4BACd,WAAW;4BACX,aAAa;4BACb,gBAAgB;4BAChB,WAAW;4BACX,eAAe;yBAChB,CAAC;AACH,qBAAA;AACD,oBAAA,QAAQ,EAAE,0BAA0B;AACpC,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFT,EAAA,CAAA;AACF,iBAAA;;;MCXY,gBAAgB,CAAA;AAClB,IAAA,OAAO,GAAG,KAAK,CAAqB,IAAI,8EAAC;AACzC,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,0EAAU;IAE/B,UAAU,GAAG,MAAM,EAAU;IAC7B,IAAI,GAAG,MAAM,EAAe;IAC5B,IAAI,GAAG,MAAM,EAAe;IAC5B,MAAM,GAAG,MAAM,EAAe;IAC9B,OAAO,GAAG,MAAM,EAAQ;IACxB,QAAQ,GAAG,MAAM,EAAQ;IACzB,YAAY,GAAG,MAAM,EAAQ;AAE5B,IAAA,UAAU,CAAC,KAAY,EAAA;AAC/B,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;AAE3B,QAAA,IAAI,MAAM,YAAY,gBAAgB,EAAE;YACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QACpC;IACF;wGAlBW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,gBAAgB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,SAAA,EAjHhB;AACT,YAAA,YAAY,CAAC;gBACX,WAAW;gBACX,kBAAkB;gBAClB,UAAU;gBACV,YAAY;gBACZ,YAAY;gBACZ,OAAO;aACR,CAAC;SACH,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAES;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGT,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAhHS,MAAM,6GAAE,WAAW,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAkHlB,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBApH5B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;AAC9B,oBAAA,SAAS,EAAE;AACT,wBAAA,YAAY,CAAC;4BACX,WAAW;4BACX,kBAAkB;4BAClB,UAAU;4BACV,YAAY;4BACZ,YAAY;4BACZ,OAAO;yBACR,CAAC;AACH,qBAAA;AACD,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoGT,EAAA,CAAA;AACF,iBAAA;;;AC7HD;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAmBU,sBAAsB,CAAA;AACxB,IAAA,SAAS,GAAG,KAAK,CAAyC,IAAI,gFAAC;;AAE/D,IAAA,KAAK,GAAG,KAAK,CAAC,sBAAsB,4EAAC;IACrC,OAAO,GAAG,MAAM,EAAQ;AAEvB,IAAA,iBAAiB,CAAC,KAAiB,EAAA;QAC3C,KAAK,CAAC,cAAc,EAAE;IACxB;AAEU,IAAA,mBAAmB,CAAC,KAAY,EAAA;QACxC,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;IACrB;wGAbW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAdvB;;;;;;;;;;;;AAYT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAdS,YAAY,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAgBX,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAlBlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,OAAO,EAAE,CAAC,YAAY,CAAC;AACvB,oBAAA,QAAQ,EAAE,0BAA0B;AACpC,oBAAA,QAAQ,EAAE;;;;;;;;;;;;AAYT,EAAA,CAAA;AACF,iBAAA;;;AClDD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;;AAEG;;;;"}
|
package/package.json
CHANGED
package/types/qalma-kit.d.ts
CHANGED
|
@@ -7,11 +7,12 @@ import { QalmaEditorController, QalmaCommandValue } from '@qalma/editor';
|
|
|
7
7
|
/**
|
|
8
8
|
* Default styling for a toolbar command button. Icon-only, square, and driven
|
|
9
9
|
* entirely by the host's shadcn-style design tokens (`text-muted-foreground`,
|
|
10
|
-
* `bg-secondary`, `bg-accent-subtle`…) so it themes with the
|
|
10
|
+
* `bg-card`, `bg-secondary`, `bg-accent-subtle`…) so it themes with the
|
|
11
|
+
* surrounding app.
|
|
11
12
|
* The `qalma-command-active` class is toggled by the `QalmaCommand` directive
|
|
12
13
|
* when the underlying command is active.
|
|
13
14
|
*/
|
|
14
|
-
declare const TOOLBAR_BUTTON_CLASS = "inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-
|
|
15
|
+
declare const TOOLBAR_BUTTON_CLASS = "inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-border bg-card text-muted-foreground transition hover:border-accent/50 hover:bg-secondary hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45 [&.qalma-command-active]:border-accent/40 [&.qalma-command-active]:bg-accent-subtle [&.qalma-command-active]:text-accent";
|
|
15
16
|
/**
|
|
16
17
|
* Generic, declarative toolbar button for a single editor command.
|
|
17
18
|
*
|
|
@@ -36,7 +37,7 @@ declare class QalmaToolbarButton {
|
|
|
36
37
|
readonly label: _angular_core.InputSignal<string>;
|
|
37
38
|
/** Optional icon-size class override (default: `text-[0.9rem]`). */
|
|
38
39
|
readonly iconClass: _angular_core.InputSignal<string>;
|
|
39
|
-
protected readonly buttonClass = "inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-
|
|
40
|
+
protected readonly buttonClass = "inline-flex h-[1.85rem] w-[1.85rem] cursor-pointer items-center justify-center rounded-[0.4rem] border border-border bg-card text-muted-foreground transition hover:border-accent/50 hover:bg-secondary hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45 [&.qalma-command-active]:border-accent/40 [&.qalma-command-active]:bg-accent-subtle [&.qalma-command-active]:text-accent";
|
|
40
41
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<QalmaToolbarButton, never>;
|
|
41
42
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<QalmaToolbarButton, "qalma-toolbar-button", never, { "command": { "alias": "command"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "iconClass": { "alias": "iconClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
42
43
|
}
|
package/types/qalma-kit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qalma-kit.d.ts","sources":["../../../../libs/ui-kit/src/lib/toolbar-button.ts","../../../../libs/ui-kit/src/lib/toolbar-commands.ts","../../../../libs/ui-kit/src/lib/toolbar-registry.ts","../../../../libs/ui-kit/src/lib/toolbar-icons.ts","../../../../libs/ui-kit/src/lib/drag-handle.ts","../../../../libs/ui-kit/src/lib/mention-menu.ts","../../../../libs/ui-kit/src/lib/slash-command-menu.ts","../../../../libs/ui-kit/src/lib/link-popover.ts","../../../../libs/ui-kit/src/lib/contextual-toolbar.ts"],"mappings":";;;;;;AAIA
|
|
1
|
+
{"version":3,"file":"qalma-kit.d.ts","sources":["../../../../libs/ui-kit/src/lib/toolbar-button.ts","../../../../libs/ui-kit/src/lib/toolbar-commands.ts","../../../../libs/ui-kit/src/lib/toolbar-registry.ts","../../../../libs/ui-kit/src/lib/toolbar-icons.ts","../../../../libs/ui-kit/src/lib/drag-handle.ts","../../../../libs/ui-kit/src/lib/mention-menu.ts","../../../../libs/ui-kit/src/lib/slash-command-menu.ts","../../../../libs/ui-kit/src/lib/link-popover.ts","../../../../libs/ui-kit/src/lib/contextual-toolbar.ts"],"mappings":";;;;;;AAIA;;;;;;;AAOG;AACH,cAAa,oBAAoB;AAGjC;;;;;;;;;;;;AAYG;AACH,cAoBa,kBAAkB;;sBAEb,aAAA,CAAA,WAAA;;oBAEF,aAAA,CAAA,WAAA;;mBAED,aAAA,CAAA,WAAA;;oBAEC,aAAA,CAAA,WAAA;;wBAEI,aAAA,CAAA,WAAA;AAElB;oDAZW,kBAAkB;sDAAlB,kBAAkB;AAa9B;;AC3DD;;;;AAIG;UACc,kBAAkB;AACjC;AACA;AACA;AACA;AACD;AAED;;;;AAIG;UACc,mBAAmB;AAClC,uBAAmB,WAAW;AAC/B;KAEW,WAAW,GAAG,kBAAkB,GAAG,mBAAmB;AAElE;KACY,YAAY,YAAY,WAAW;AAE/C,iBAAgB,oBAAoB,OAC5B,WAAW,WACR,kBAAkB;AAW7B,cAAa,sBAAsB,WAAW,kBAAkB;AAOhE,cAAa,0BAA0B,WAAW,kBAAkB;AAmBpE,cAAa,mBAAmB,WAAW,kBAAkB;AAmB7D,cAAa,mBAAmB,WAAW,kBAAkB;AAc7D;AACA,cAAa,0BAA0B,EAAE,kBAIxC;AAED;AACA,cAAa,uBAAuB,WAAW,kBAAkB;AAqBjE,cAAa,qBAAqB,WAAW,kBAAkB;AAK/D;AACA,cAAa,8BAA8B,EAAE,kBAI5C;AAED;AACA,cAAa,wBAAwB,EAAE,kBAItC;;AChID;AACA,cAAa,uBAAuB;AAGpC;;;;;;;;;;;;;;;AAeG;AACH,cA2Ba,oBAAoB;qBAChB,aAAA,CAAA,WAAA,UAAA,YAAA;6BACQ,aAAA,CAAA,WAAA;;AAGvB,sCAAgC,aAAA,CAAA,MAAA,CAAA,YAAA;8BAIN,WAAW,GAAG,kBAAkB;+BAI/B,WAAW,GAAG,WAAW;oDAbzC,oBAAoB;sDAApB,oBAAoB;AAgBhC;;AC3CD;;;;;;;;;;;AAWG;AACH,iBAAgB,wBAAwB,IAAA,aAAA,CAAA,QAAA;;UCrBvB,cAAc;WACtB,YAAY;YACX,mBAAmB;AAC5B;AAED,cAmIa,eAAe;qBACX,aAAA,CAAA,WAAA,CAAA,qBAAA;qBACA,aAAA,CAAA,WAAA,CAAA,mBAAA;4BACO,aAAA,CAAA,WAAA,CAAA,sBAAA;oCACQ,aAAA,CAAA,WAAA,CAAA,uBAAA;sBAGd,aAAA,CAAA,gBAAA;wBACE,aAAA,CAAA,gBAAA,CAAA,cAAA;AAElB,iCAA2B,aAAA,CAAA,cAAA;;;+BAoBlB,YAAY,UACX,mBAAmB;kDAQnB,mBAAmB;+CAKc,mBAAmB;AAM9D,uCAAmC,UAAU;AAI7C,yCAAqC,KAAK;;oDAtD/B,eAAe;sDAAf,eAAe;AA+D3B;;UChOgB,kBAAkB;AACjC;AACA;AACA;AACD;AAED;;;;;AAKG;AACH,cAgFa,gBAAiB,SAAQ,mBAAmB,CAAC,kBAAkB;0BACtD,aAAA,CAAA,WAAA,UAAA,kBAAA;sBACJ,aAAA,CAAA,WAAA;AAEhB,mCAA6B,aAAA,CAAA,WAAA,UAAA,kBAAA;oDAJlB,gBAAgB;sDAAhB,gBAAgB;AAK5B;;UC5EgB,uBAAuB;AACtC;AACA;AACA;AACA;AACA;;AAEA;AACA,qBAAiB,iBAAiB;AAClC;;AAEA;AACD;AAED;;;;;;AAMG;AACH,cAsGa,qBAAsB,SAAQ,mBAAmB,CAAC,uBAAuB;sBACpE,aAAA,CAAA,WAAA,UAAA,uBAAA;AAEhB,mCAA6B,aAAA,CAAA,WAAA,UAAA,uBAAA;;oDAHlB,qBAAqB;sDAArB,qBAAqB;AAejC;;AC/ID,cAoHa,gBAAgB;sBACX,aAAA,CAAA,WAAA,CAAA,WAAA;mBACH,aAAA,CAAA,WAAA;yBAEM,aAAA,CAAA,gBAAA;mBACN,aAAA,CAAA,gBAAA,CAAA,WAAA;mBACA,aAAA,CAAA,gBAAA,CAAA,WAAA;qBACE,aAAA,CAAA,gBAAA,CAAA,WAAA;sBACC,aAAA,CAAA,gBAAA;uBACC,aAAA,CAAA,gBAAA;2BACI,aAAA,CAAA,gBAAA;AAErB,gCAA4B,KAAK;oDAZtB,gBAAgB;sDAAhB,gBAAgB;AAmB5B;;ACjJD;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACH,cAkBa,sBAAsB;wBACf,aAAA,CAAA,WAAA,CAAA,+BAAA;;oBAEJ,aAAA,CAAA,WAAA;sBACE,aAAA,CAAA,gBAAA;AAEhB,uCAAmC,UAAU;AAI7C,yCAAqC,KAAK;oDAV/B,sBAAsB;sDAAtB,sBAAsB;AAclC;;;;","names":[]}
|