ngwr 13.0.1 → 14.0.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 +13 -6
- package/color-picker/styles/_index.scss +43 -5
- package/fesm2022/ngwr-alert.mjs +5 -5
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-back-top.mjs +11 -1
- package/fesm2022/ngwr-back-top.mjs.map +1 -1
- package/fesm2022/ngwr-blur-text.mjs +13 -2
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-button.mjs +4 -4
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-testing.mjs +15 -0
- package/fesm2022/ngwr-calendar-testing.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +51 -5
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +20 -1
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-collapse.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker-testing.mjs +23 -7
- package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker.mjs +89 -10
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +27 -3
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu.mjs +7 -1
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapters-fns.mjs +101 -33
- package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker-testing.mjs +10 -2
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +103 -13
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-date.mjs +480 -79
- package/fesm2022/ngwr-date.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +30 -2
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +2 -1
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +1 -1
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload.mjs +52 -12
- package/fesm2022/ngwr-file-upload.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +63 -1
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +28 -1
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +150 -22
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +3 -3
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +21 -3
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +14 -7
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +20 -2
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar-router.mjs +73 -0
- package/fesm2022/ngwr-loading-bar-router.mjs.map +1 -0
- package/fesm2022/ngwr-loading-bar.mjs +21 -32
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-mention.mjs +104 -14
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-pagination-testing.mjs +11 -10
- package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +65 -30
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-popconfirm.mjs +3 -2
- package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +2 -1
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +93 -34
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-splitter-testing.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +2 -1
- package/fesm2022/ngwr-squircle.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +35 -4
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +35 -12
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-router.mjs +158 -0
- package/fesm2022/ngwr-tabs-router.mjs.map +1 -0
- package/fesm2022/ngwr-tabs-testing.mjs +13 -11
- package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +98 -10
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +20 -1
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-tour.mjs +1 -1
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-transfer.mjs +2 -2
- package/fesm2022/ngwr-transfer.mjs.map +1 -1
- package/fesm2022/ngwr-tree.mjs +18 -2
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-utils.mjs +37 -1
- package/fesm2022/ngwr-utils.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-window-testing.mjs +10 -2
- package/fesm2022/ngwr-window-testing.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +4 -4
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/i18n/en.json +33 -6
- package/i18n/ru.json +33 -6
- package/llms-full.txt +20 -11
- package/llms.txt +47 -16
- package/mcp/catalog.js +3 -3
- package/mcp/providers.js +11 -0
- package/package.json +9 -1
- package/schematics/migrations/v13/index.js +101 -0
- package/schematics/migrations/v14/index.js +422 -0
- package/schematics/migrations.json +10 -0
- package/schematics/page/templates.js +1 -1
- package/schematics/use/symbol-map.json +1 -0
- package/skills/ngwr/SKILL.md +4 -1
- package/skills/ngwr/references/catalog.md +2 -0
- package/skills/ngwr/references/setup.md +4 -0
- package/stepper/styles/_index.scss +19 -1
- package/textarea/styles/_index.scss +14 -6
- package/toast/styles/_index.scss +12 -4
- package/types/ngwr-alert.d.ts +3 -3
- package/types/ngwr-blur-text.d.ts +8 -0
- package/types/ngwr-button.d.ts +2 -2
- package/types/ngwr-calendar-testing.d.ts +21 -4
- package/types/ngwr-calendar.d.ts +37 -0
- package/types/ngwr-circular-text.d.ts +9 -0
- package/types/ngwr-collapse.d.ts +19 -15
- package/types/ngwr-color-picker-testing.d.ts +10 -4
- package/types/ngwr-color-picker.d.ts +70 -2
- package/types/ngwr-command-palette.d.ts +14 -0
- package/types/ngwr-context-menu.d.ts +1 -1
- package/types/ngwr-date-adapters-fns.d.ts +71 -29
- package/types/ngwr-date-picker-testing.d.ts +206 -185
- package/types/ngwr-date-picker.d.ts +7 -0
- package/types/ngwr-date.d.ts +143 -13
- package/types/ngwr-drag-drop.d.ts +19 -0
- package/types/ngwr-dropdown.d.ts +1 -1
- package/types/ngwr-event-calendar-testing.d.ts +12 -9
- package/types/ngwr-file-upload.d.ts +31 -3
- package/types/ngwr-i18n.d.ts +89 -7
- package/types/ngwr-input-number.d.ts +1 -1
- package/types/ngwr-input-otp.d.ts +3 -0
- package/types/ngwr-input.d.ts +11 -4
- package/types/ngwr-knob-testing.d.ts +8 -4
- package/types/ngwr-knob.d.ts +18 -0
- package/types/ngwr-loading-bar-router.d.ts +35 -0
- package/types/ngwr-loading-bar.d.ts +19 -9
- package/types/ngwr-mention.d.ts +13 -0
- package/types/ngwr-pagination-testing.d.ts +11 -10
- package/types/ngwr-pagination.d.ts +39 -10
- package/types/ngwr-popconfirm.d.ts +1 -1
- package/types/ngwr-popover.d.ts +1 -1
- package/types/ngwr-select.d.ts +65 -10
- package/types/ngwr-splitter-testing.d.ts +9 -4
- package/types/ngwr-squircle.d.ts +1 -1
- package/types/ngwr-statistic.d.ts +22 -2
- package/types/ngwr-table.d.ts +24 -5
- package/types/ngwr-tabs-router.d.ts +67 -0
- package/types/ngwr-tabs-testing.d.ts +12 -10
- package/types/ngwr-tabs.d.ts +103 -6
- package/types/ngwr-textarea.d.ts +9 -0
- package/types/ngwr-tree.d.ts +7 -0
- package/types/ngwr-utils.d.ts +33 -1
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-window-testing.d.ts +11 -3
- package/types/ngwr-window.d.ts +11 -4
- package/window/styles/_index.scss +1 -1
|
@@ -95,9 +95,17 @@ class WrWindowHarness extends ContentContainerComponentHarness {
|
|
|
95
95
|
}
|
|
96
96
|
throw new Error('WrWindowHarness.getOs(): this window carries no `wr-window--os-<name>` class.');
|
|
97
97
|
}
|
|
98
|
-
/**
|
|
98
|
+
/**
|
|
99
|
+
* The title-bar density — `sm` or `md`.
|
|
100
|
+
*
|
|
101
|
+
* Typed as the union rather than `string`, so a value added to
|
|
102
|
+
* `WrWindowChromeSize` fails this method's compile instead of quietly
|
|
103
|
+
* answering `md` for it. Only `sm` carries a modifier class: `md` is the
|
|
104
|
+
* default and paints from the base block, so its answer is the absence of
|
|
105
|
+
* the other one.
|
|
106
|
+
*/
|
|
99
107
|
async getChromeSize() {
|
|
100
|
-
return (await (await this.host()).hasClass('wr-window--chrome-
|
|
108
|
+
return (await (await this.host()).hasClass('wr-window--chrome-sm')) ? 'sm' : 'md';
|
|
101
109
|
}
|
|
102
110
|
/**
|
|
103
111
|
* Where the window is and how big, in CSS pixels.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-window-testing.mjs","sources":["../../../projects/lib/window/testing/wr-window-harness.ts","../../../projects/lib/window/testing/wr-window-taskbar-harness.ts","../../../projects/lib/window/testing/ngwr-window-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ContentContainerComponentHarness, HarnessPredicate, TestKey, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrWindowState } from 'ngwr/window';\n\nimport type { WrWindowBox, WrWindowHarnessFilters } from './interfaces';\n\nconst STATES: readonly WrWindowState[] = ['normal', 'minimized', 'maximized'];\n\n/**\n * Test harness for a window opened through `WrWindowManager.open()`.\n *\n * `WrWindow` is deliberately not exported — a window is always a service call — so\n * there is nothing in your fixture to load: each window is a portal in its own\n * overlay pane, and this comes from\n * `TestbedHarnessEnvironment.documentRootLoader()`.\n *\n * It is a CONTENT CONTAINER, like `WrDialogHarness`: the component you opened is\n * projected into the window's body, so `window.getHarness(WrButtonHarness…)` reads\n * ITS buttons and cannot reach another window's. That matters more here than\n * anywhere else, because windows are explicitly non-modal and several are normally\n * open at once.\n *\n * **Geometry is read from the inline styles the component writes**, never measured:\n * a window is positioned with `left` / `top` / `width` / `height` in pixels, and a\n * unit test has no layout to measure. That also makes {@link getBox} the way to\n * assert a move or a resize — including the ones a drag would produce, which no\n * synthetic pointer event can, since the drag divides by a rect that is 0×0 here.\n *\n * @example\n * ```ts\n * const rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);\n * windows.open(EditorComponent, { title: 'Untitled.md' });\n * await fixture.whenStable();\n *\n * const win = await rootLoader.getHarness(WrWindowHarness.with({ title: 'Untitled.md' }));\n * await win.maximize();\n * expect(await win.getState()).toBe('maximized');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrWindowHarness extends ContentContainerComponentHarness {\n static hostSelector = 'wr-window';\n\n /** Build a predicate that narrows the query — windows come in stacks. */\n static with(options: WrWindowHarnessFilters = {}): HarnessPredicate<WrWindowHarness> {\n return new HarnessPredicate(WrWindowHarness, options)\n .addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitle(), title))\n .addOption('state', options.state, async (harness, state) => (await harness.getState()) === state);\n }\n\n private readonly titleEl = this.locatorFor('.wr-window__title');\n\n /**\n * Whether this window is still on the page.\n *\n * For a harness you are already HOLDING: closing disposes the overlay, so this\n * flips to `false` where a fresh `getHarnessOrNull()` comes back `null`. A\n * MINIMIZED window is still open — it is a state, not a dismissal — and this\n * stays `true` for one.\n */\n async isOpen(): Promise<boolean> {\n return (await this.host()).matchesSelector('body wr-window');\n }\n\n /** The title-bar text. */\n async getTitle(): Promise<string> {\n return (await this.titleEl()).text();\n }\n\n /** The projected `[wrWindowTitleExtra]` content, trimmed — empty when there is none. */\n async getTitleExtraText(): Promise<string> {\n return (await this.locatorFor('.wr-window__title-extra')()).text();\n }\n\n /** The window's visual state, from the host modifier. */\n async getState(): Promise<WrWindowState> {\n const host = await this.host();\n for (const state of STATES) {\n if (await host.hasClass(`wr-window--${state}`)) return state;\n }\n throw new Error(\n 'WrWindowHarness.getState(): this host carries no `wr-window--<state>` class, which every window sets — ' +\n 'the element matched is probably not an ngwr window.'\n );\n }\n\n /**\n * The OS the chrome is dressed as — `macos`, `windows` or `linux`.\n *\n * Worth asserting because it is not cosmetic: on macOS the buttons are a\n * traffic-light cluster in close → minimize → maximize order, and the Linux\n * chrome renders neither minimize nor maximize UNLESS `showMinimize` /\n * `showMaximize` asks for them. \"No minimize on Linux\" is a default, not an\n * invariant — see {@link hasMinimizeButton}.\n */\n async getOs(): Promise<string> {\n const host = await this.host();\n for (const os of ['macos', 'windows', 'linux']) {\n if (await host.hasClass(`wr-window--os-${os}`)) return os;\n }\n throw new Error('WrWindowHarness.getOs(): this window carries no `wr-window--os-<name>` class.');\n }\n\n /** The title-bar density — `normal` or `compact`. */\n async getChromeSize(): Promise<string> {\n return (await (await this.host()).hasClass('wr-window--chrome-compact')) ? 'compact' : 'normal';\n }\n\n /**\n * Where the window is and how big, in CSS pixels.\n *\n * From the inline styles the component writes, which is the only readable answer\n * without layout — and the same numbers a drag or a snap would change.\n */\n async getBox(): Promise<WrWindowBox> {\n const host = await this.host();\n return {\n x: Number.parseFloat(await host.getCssValue('left')),\n y: Number.parseFloat(await host.getCssValue('top')),\n width: Number.parseFloat(await host.getCssValue('width')),\n height: Number.parseFloat(await host.getCssValue('height')),\n };\n }\n\n /**\n * The window's stacking order.\n *\n * The manager hands out a z-index per focus, so this is how a spec asserts that\n * clicking a window brought it to the front — the one thing a window manager\n * exists to do, and the reason these panes are deliberately kept OUT of the\n * browser's top layer, which orders strictly by entry.\n */\n async getZIndex(): Promise<number> {\n return Number.parseFloat(await (await this.host()).getCssValue('z-index'));\n }\n\n /** Whether the resize handles are rendered — `resizable`, and only in the normal state. */\n async isResizable(): Promise<boolean> {\n return (await this.host()).hasClass('wr-window--resizable');\n }\n\n /** The resize handles currently rendered, by their edge / corner suffix. */\n async getResizeHandles(): Promise<string[]> {\n const handles = await this.locatorForAll('.wr-window__handle')();\n return Promise.all(\n handles.map(async handle => {\n const classes = (await handle.getAttribute('class')) ?? '';\n return (\n classes\n .split(/\\s+/)\n .find(name => name.startsWith('wr-window__handle--'))\n ?.slice(19) ?? ''\n );\n })\n );\n }\n\n /** The body text of the window — the component you opened, as rendered. */\n async getBodyText(): Promise<string> {\n return (await this.locatorFor('.wr-window__body')()).text();\n }\n\n /** The projected `[wrWindowStatusBar]` content, trimmed. */\n async getStatusBarText(): Promise<string> {\n return (await this.locatorFor('.wr-window__status-bar')()).text();\n }\n\n /** Whether the chrome offers a close button (`showClose`). */\n async hasCloseButton(): Promise<boolean> {\n return (await this.chromeAction('close')) !== null;\n }\n\n /**\n * Whether the chrome offers a minimize button.\n *\n * `false` on Linux BY DEFAULT — that chrome is close-only by convention, which\n * is a real behavioural difference and not a style. `showMinimize: true`\n * overrides it, and a spec that asserts \"no minimize on Linux\" without saying\n * which of the two it means will pass for the wrong reason.\n */\n async hasMinimizeButton(): Promise<boolean> {\n return (await this.chromeAction('minimize')) !== null;\n }\n\n /** Whether the chrome offers a maximize button. Also `false` on Linux by default. */\n async hasMaximizeButton(): Promise<boolean> {\n return (await this.chromeAction('maximize')) !== null;\n }\n\n /** The close button's accessible name — the buttons are icon-only, so it is their only name. */\n async getCloseLabel(): Promise<string | null> {\n return (await this.requireAction('close', 'getCloseLabel')).getAttribute('aria-label');\n }\n\n /**\n * The minimize button's accessible name, which flips to the restore wording while\n * the window is minimized — the same button does both.\n */\n async getMinimizeLabel(): Promise<string | null> {\n return (await this.requireAction('minimize', 'getMinimizeLabel')).getAttribute('aria-label');\n }\n\n /** The maximize button's accessible name, which flips while the window is maximized. */\n async getMaximizeLabel(): Promise<string | null> {\n return (await this.requireAction('maximize', 'getMaximizeLabel')).getAttribute('aria-label');\n }\n\n /** Click the close button. Throws on a window opened `showClose: false`. */\n async close(): Promise<void> {\n await (await this.requireAction('close', 'close')).click();\n }\n\n /**\n * Click the minimize button — which RESTORES a minimized window, since it is the\n * same control.\n */\n async minimize(): Promise<void> {\n await (await this.requireAction('minimize', 'minimize')).click();\n }\n\n /** Click the maximize button — which restores a maximized window down. */\n async maximize(): Promise<void> {\n await (await this.requireAction('maximize', 'maximize')).click();\n }\n\n /**\n * Double-click the title bar, the other way to maximize.\n *\n * A separate gesture worth its own assertion, and it does NOT follow the\n * button: only an explicit `showMaximize: false` turns it off. The Linux\n * chrome hides the button by convention and keeps the gesture — which is also\n * the only way out of a window that reached `maximized` without one.\n */\n async doubleClickChrome(): Promise<void> {\n await (await this.locatorFor('.wr-window__chrome')()).dispatchEvent('dblclick');\n }\n\n /** Click the window body — which pulls it to the front of the stack. */\n async focusWindow(): Promise<void> {\n await (await this.host()).click();\n }\n\n /** Press Escape. A window opened `closeOnEscape: false` ignores it — assert, do not assume. */\n async sendEscape(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ESCAPE);\n }\n\n /** The role the window announces — `dialog`, on a non-modal window. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /**\n * Whether the window takes its accessible name from its own title element.\n *\n * Resolved rather than trusted: `aria-labelledby` naming an element that is not\n * this window's title is not a name, and with several windows open the ids are\n * the only thing keeping them apart.\n */\n async isLabelledByTitle(): Promise<boolean> {\n const labelledBy = await (await this.host()).getAttribute('aria-labelledby');\n if (!labelledBy) return false;\n return (await (await this.titleEl()).getAttribute('id')) === labelledBy;\n }\n\n /** Whether the window is hidden from assistive tech (`aria-hidden`, set while closed). */\n async isHiddenFromAssistiveTech(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-hidden')) === 'true';\n }\n\n private async chromeAction(name: 'close' | 'minimize' | 'maximize'): Promise<TestElement | null> {\n return this.locatorForOptional(`.wr-window__chrome-action--${name}`)();\n }\n\n private async requireAction(name: 'close' | 'minimize' | 'maximize', method: string): Promise<TestElement> {\n const button = await this.chromeAction(name);\n if (!button) {\n throw new Error(\n `WrWindowHarness.${method}(): this window has no ${name} button. It was opened with \\`show` +\n `${name[0].toUpperCase()}${name.slice(1)}: false\\`, or its chrome is the Linux one, which is ` +\n `close-only unless \\`show${name[0].toUpperCase()}${name.slice(1)}: true\\` asks for it.`\n );\n }\n return button;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrWindowTaskbarHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `<wr-window-taskbar>` — the rail of minimized windows.\n *\n * The taskbar IS an element in your template, so it comes from the normal fixture\n * loader, unlike the windows it lists. It renders nothing but its own host until a\n * window is minimized; {@link isEmpty} is the question, and {@link getTabTitles}\n * answers `[]` rather than throwing, because \"no minimized windows\" is the ordinary\n * state rather than a mistake.\n *\n * @example\n * ```ts\n * const taskbar = await loader.getHarness(WrWindowTaskbarHarness);\n *\n * await (await rootLoader.getHarness(WrWindowHarness)).minimize();\n * expect(await taskbar.getTabTitles()).toEqual(['Untitled.md']);\n * await taskbar.restore('Untitled.md');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrWindowTaskbarHarness extends ComponentHarness {\n static hostSelector = 'wr-window-taskbar';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrWindowTaskbarHarnessFilters = {}): HarnessPredicate<WrWindowTaskbarHarness> {\n return new HarnessPredicate(WrWindowTaskbarHarness, options).addOption(\n 'position',\n options.position,\n async (harness, position) => (await harness.getPosition()) === position\n );\n }\n\n /** The edge the rail is pinned to. */\n async getPosition(): Promise<'top' | 'bottom'> {\n return (await (await this.host()).hasClass('wr-window-taskbar--top')) ? 'top' : 'bottom';\n }\n\n /**\n * The rail's accessible name — it is a `role=\"toolbar\"`, and an unnamed one is\n * announced as nothing.\n */\n async getRailLabel(): Promise<string | null> {\n return (await this.host()).getAttribute('aria-label');\n }\n\n /** Whether nothing is minimized — the rail draws no markup at all then. */\n async isEmpty(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-window-taskbar__rail')()) === null;\n }\n\n /**\n * The titles in the rail, in order.\n *\n * A window opened without a title still gets a tab, named by the catalog's\n * fallback rather than left blank — a nameless tab is unreachable by voice and\n * indistinguishable from its neighbours.\n */\n async getTabTitles(): Promise<string[]> {\n const titles = await this.locatorForAll('.wr-window-taskbar__tab-title')();\n return Promise.all(titles.map(title => title.text()));\n }\n\n /** A tab's accessible name — the restore wording with the window's title in it. */\n async getRestoreLabel(title: string): Promise<string | null> {\n return (await this.requireTab(title, 'getRestoreLabel')).getAttribute('aria-label');\n }\n\n /** Click a tab — restoring that window and focusing it. */\n async restore(title: string): Promise<void> {\n await (await this.requireTab(title, 'restore')).click();\n }\n\n /**\n * Click a tab's ✕ — closing the window WITHOUT restoring it.\n *\n * Still worth asserting separately now that the two are siblings rather than\n * nested: they sit inside one pill and look like one control, so a close that\n * also restored would flash a closing window's content and look plausible.\n */\n async closeTab(title: string): Promise<void> {\n const index = await this.indexOf(title, 'closeTab');\n const closers = await this.locatorForAll('.wr-window-taskbar__tab-close')();\n await closers[index].click();\n }\n\n /**\n * The tab's BUTTON, not the pill around it.\n *\n * `.wr-window-taskbar__tab` is a plain container — it carries the pill's look\n * and nothing else, because the close beside it cannot be a control nested in\n * a control. The name and the click both belong to `__tab-restore`.\n */\n private async requireTab(title: string, method: string): Promise<TestElement> {\n const tabs = await this.locatorForAll('.wr-window-taskbar__tab-restore')();\n return tabs[await this.indexOf(title, method)];\n }\n\n /** Which tab carries this title — one lookup for both the tab and its close button. */\n private async indexOf(title: string, method: string): Promise<number> {\n const tabs = await this.locatorForAll('.wr-window-taskbar__tab-restore')();\n for (const [index, tab] of tabs.entries()) {\n if ((await tab.text()) === title) return index;\n }\n\n const offered = await this.getTabTitles();\n throw new Error(\n `WrWindowTaskbarHarness.${method}(\"${title}\"): no such tab. The rail holds: ` +\n `${offered.length ? offered.join(', ') : '(nothing — no window is minimized)'}.`\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-window-testing.mjs","sources":["../../../projects/lib/window/testing/wr-window-harness.ts","../../../projects/lib/window/testing/wr-window-taskbar-harness.ts","../../../projects/lib/window/testing/ngwr-window-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ContentContainerComponentHarness, HarnessPredicate, TestKey, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrWindowChromeSize, WrWindowState } from 'ngwr/window';\n\nimport type { WrWindowBox, WrWindowHarnessFilters } from './interfaces';\n\nconst STATES: readonly WrWindowState[] = ['normal', 'minimized', 'maximized'];\n\n/**\n * Test harness for a window opened through `WrWindowManager.open()`.\n *\n * `WrWindow` is deliberately not exported — a window is always a service call — so\n * there is nothing in your fixture to load: each window is a portal in its own\n * overlay pane, and this comes from\n * `TestbedHarnessEnvironment.documentRootLoader()`.\n *\n * It is a CONTENT CONTAINER, like `WrDialogHarness`: the component you opened is\n * projected into the window's body, so `window.getHarness(WrButtonHarness…)` reads\n * ITS buttons and cannot reach another window's. That matters more here than\n * anywhere else, because windows are explicitly non-modal and several are normally\n * open at once.\n *\n * **Geometry is read from the inline styles the component writes**, never measured:\n * a window is positioned with `left` / `top` / `width` / `height` in pixels, and a\n * unit test has no layout to measure. That also makes {@link getBox} the way to\n * assert a move or a resize — including the ones a drag would produce, which no\n * synthetic pointer event can, since the drag divides by a rect that is 0×0 here.\n *\n * @example\n * ```ts\n * const rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);\n * windows.open(EditorComponent, { title: 'Untitled.md' });\n * await fixture.whenStable();\n *\n * const win = await rootLoader.getHarness(WrWindowHarness.with({ title: 'Untitled.md' }));\n * await win.maximize();\n * expect(await win.getState()).toBe('maximized');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrWindowHarness extends ContentContainerComponentHarness {\n static hostSelector = 'wr-window';\n\n /** Build a predicate that narrows the query — windows come in stacks. */\n static with(options: WrWindowHarnessFilters = {}): HarnessPredicate<WrWindowHarness> {\n return new HarnessPredicate(WrWindowHarness, options)\n .addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitle(), title))\n .addOption('state', options.state, async (harness, state) => (await harness.getState()) === state);\n }\n\n private readonly titleEl = this.locatorFor('.wr-window__title');\n\n /**\n * Whether this window is still on the page.\n *\n * For a harness you are already HOLDING: closing disposes the overlay, so this\n * flips to `false` where a fresh `getHarnessOrNull()` comes back `null`. A\n * MINIMIZED window is still open — it is a state, not a dismissal — and this\n * stays `true` for one.\n */\n async isOpen(): Promise<boolean> {\n return (await this.host()).matchesSelector('body wr-window');\n }\n\n /** The title-bar text. */\n async getTitle(): Promise<string> {\n return (await this.titleEl()).text();\n }\n\n /** The projected `[wrWindowTitleExtra]` content, trimmed — empty when there is none. */\n async getTitleExtraText(): Promise<string> {\n return (await this.locatorFor('.wr-window__title-extra')()).text();\n }\n\n /** The window's visual state, from the host modifier. */\n async getState(): Promise<WrWindowState> {\n const host = await this.host();\n for (const state of STATES) {\n if (await host.hasClass(`wr-window--${state}`)) return state;\n }\n throw new Error(\n 'WrWindowHarness.getState(): this host carries no `wr-window--<state>` class, which every window sets — ' +\n 'the element matched is probably not an ngwr window.'\n );\n }\n\n /**\n * The OS the chrome is dressed as — `macos`, `windows` or `linux`.\n *\n * Worth asserting because it is not cosmetic: on macOS the buttons are a\n * traffic-light cluster in close → minimize → maximize order, and the Linux\n * chrome renders neither minimize nor maximize UNLESS `showMinimize` /\n * `showMaximize` asks for them. \"No minimize on Linux\" is a default, not an\n * invariant — see {@link hasMinimizeButton}.\n */\n async getOs(): Promise<string> {\n const host = await this.host();\n for (const os of ['macos', 'windows', 'linux']) {\n if (await host.hasClass(`wr-window--os-${os}`)) return os;\n }\n throw new Error('WrWindowHarness.getOs(): this window carries no `wr-window--os-<name>` class.');\n }\n\n /**\n * The title-bar density — `sm` or `md`.\n *\n * Typed as the union rather than `string`, so a value added to\n * `WrWindowChromeSize` fails this method's compile instead of quietly\n * answering `md` for it. Only `sm` carries a modifier class: `md` is the\n * default and paints from the base block, so its answer is the absence of\n * the other one.\n */\n async getChromeSize(): Promise<WrWindowChromeSize> {\n return (await (await this.host()).hasClass('wr-window--chrome-sm')) ? 'sm' : 'md';\n }\n\n /**\n * Where the window is and how big, in CSS pixels.\n *\n * From the inline styles the component writes, which is the only readable answer\n * without layout — and the same numbers a drag or a snap would change.\n */\n async getBox(): Promise<WrWindowBox> {\n const host = await this.host();\n return {\n x: Number.parseFloat(await host.getCssValue('left')),\n y: Number.parseFloat(await host.getCssValue('top')),\n width: Number.parseFloat(await host.getCssValue('width')),\n height: Number.parseFloat(await host.getCssValue('height')),\n };\n }\n\n /**\n * The window's stacking order.\n *\n * The manager hands out a z-index per focus, so this is how a spec asserts that\n * clicking a window brought it to the front — the one thing a window manager\n * exists to do, and the reason these panes are deliberately kept OUT of the\n * browser's top layer, which orders strictly by entry.\n */\n async getZIndex(): Promise<number> {\n return Number.parseFloat(await (await this.host()).getCssValue('z-index'));\n }\n\n /** Whether the resize handles are rendered — `resizable`, and only in the normal state. */\n async isResizable(): Promise<boolean> {\n return (await this.host()).hasClass('wr-window--resizable');\n }\n\n /** The resize handles currently rendered, by their edge / corner suffix. */\n async getResizeHandles(): Promise<string[]> {\n const handles = await this.locatorForAll('.wr-window__handle')();\n return Promise.all(\n handles.map(async handle => {\n const classes = (await handle.getAttribute('class')) ?? '';\n return (\n classes\n .split(/\\s+/)\n .find(name => name.startsWith('wr-window__handle--'))\n ?.slice(19) ?? ''\n );\n })\n );\n }\n\n /** The body text of the window — the component you opened, as rendered. */\n async getBodyText(): Promise<string> {\n return (await this.locatorFor('.wr-window__body')()).text();\n }\n\n /** The projected `[wrWindowStatusBar]` content, trimmed. */\n async getStatusBarText(): Promise<string> {\n return (await this.locatorFor('.wr-window__status-bar')()).text();\n }\n\n /** Whether the chrome offers a close button (`showClose`). */\n async hasCloseButton(): Promise<boolean> {\n return (await this.chromeAction('close')) !== null;\n }\n\n /**\n * Whether the chrome offers a minimize button.\n *\n * `false` on Linux BY DEFAULT — that chrome is close-only by convention, which\n * is a real behavioural difference and not a style. `showMinimize: true`\n * overrides it, and a spec that asserts \"no minimize on Linux\" without saying\n * which of the two it means will pass for the wrong reason.\n */\n async hasMinimizeButton(): Promise<boolean> {\n return (await this.chromeAction('minimize')) !== null;\n }\n\n /** Whether the chrome offers a maximize button. Also `false` on Linux by default. */\n async hasMaximizeButton(): Promise<boolean> {\n return (await this.chromeAction('maximize')) !== null;\n }\n\n /** The close button's accessible name — the buttons are icon-only, so it is their only name. */\n async getCloseLabel(): Promise<string | null> {\n return (await this.requireAction('close', 'getCloseLabel')).getAttribute('aria-label');\n }\n\n /**\n * The minimize button's accessible name, which flips to the restore wording while\n * the window is minimized — the same button does both.\n */\n async getMinimizeLabel(): Promise<string | null> {\n return (await this.requireAction('minimize', 'getMinimizeLabel')).getAttribute('aria-label');\n }\n\n /** The maximize button's accessible name, which flips while the window is maximized. */\n async getMaximizeLabel(): Promise<string | null> {\n return (await this.requireAction('maximize', 'getMaximizeLabel')).getAttribute('aria-label');\n }\n\n /** Click the close button. Throws on a window opened `showClose: false`. */\n async close(): Promise<void> {\n await (await this.requireAction('close', 'close')).click();\n }\n\n /**\n * Click the minimize button — which RESTORES a minimized window, since it is the\n * same control.\n */\n async minimize(): Promise<void> {\n await (await this.requireAction('minimize', 'minimize')).click();\n }\n\n /** Click the maximize button — which restores a maximized window down. */\n async maximize(): Promise<void> {\n await (await this.requireAction('maximize', 'maximize')).click();\n }\n\n /**\n * Double-click the title bar, the other way to maximize.\n *\n * A separate gesture worth its own assertion, and it does NOT follow the\n * button: only an explicit `showMaximize: false` turns it off. The Linux\n * chrome hides the button by convention and keeps the gesture — which is also\n * the only way out of a window that reached `maximized` without one.\n */\n async doubleClickChrome(): Promise<void> {\n await (await this.locatorFor('.wr-window__chrome')()).dispatchEvent('dblclick');\n }\n\n /** Click the window body — which pulls it to the front of the stack. */\n async focusWindow(): Promise<void> {\n await (await this.host()).click();\n }\n\n /** Press Escape. A window opened `closeOnEscape: false` ignores it — assert, do not assume. */\n async sendEscape(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ESCAPE);\n }\n\n /** The role the window announces — `dialog`, on a non-modal window. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /**\n * Whether the window takes its accessible name from its own title element.\n *\n * Resolved rather than trusted: `aria-labelledby` naming an element that is not\n * this window's title is not a name, and with several windows open the ids are\n * the only thing keeping them apart.\n */\n async isLabelledByTitle(): Promise<boolean> {\n const labelledBy = await (await this.host()).getAttribute('aria-labelledby');\n if (!labelledBy) return false;\n return (await (await this.titleEl()).getAttribute('id')) === labelledBy;\n }\n\n /** Whether the window is hidden from assistive tech (`aria-hidden`, set while closed). */\n async isHiddenFromAssistiveTech(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-hidden')) === 'true';\n }\n\n private async chromeAction(name: 'close' | 'minimize' | 'maximize'): Promise<TestElement | null> {\n return this.locatorForOptional(`.wr-window__chrome-action--${name}`)();\n }\n\n private async requireAction(name: 'close' | 'minimize' | 'maximize', method: string): Promise<TestElement> {\n const button = await this.chromeAction(name);\n if (!button) {\n throw new Error(\n `WrWindowHarness.${method}(): this window has no ${name} button. It was opened with \\`show` +\n `${name[0].toUpperCase()}${name.slice(1)}: false\\`, or its chrome is the Linux one, which is ` +\n `close-only unless \\`show${name[0].toUpperCase()}${name.slice(1)}: true\\` asks for it.`\n );\n }\n return button;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrWindowTaskbarHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `<wr-window-taskbar>` — the rail of minimized windows.\n *\n * The taskbar IS an element in your template, so it comes from the normal fixture\n * loader, unlike the windows it lists. It renders nothing but its own host until a\n * window is minimized; {@link isEmpty} is the question, and {@link getTabTitles}\n * answers `[]` rather than throwing, because \"no minimized windows\" is the ordinary\n * state rather than a mistake.\n *\n * @example\n * ```ts\n * const taskbar = await loader.getHarness(WrWindowTaskbarHarness);\n *\n * await (await rootLoader.getHarness(WrWindowHarness)).minimize();\n * expect(await taskbar.getTabTitles()).toEqual(['Untitled.md']);\n * await taskbar.restore('Untitled.md');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrWindowTaskbarHarness extends ComponentHarness {\n static hostSelector = 'wr-window-taskbar';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrWindowTaskbarHarnessFilters = {}): HarnessPredicate<WrWindowTaskbarHarness> {\n return new HarnessPredicate(WrWindowTaskbarHarness, options).addOption(\n 'position',\n options.position,\n async (harness, position) => (await harness.getPosition()) === position\n );\n }\n\n /** The edge the rail is pinned to. */\n async getPosition(): Promise<'top' | 'bottom'> {\n return (await (await this.host()).hasClass('wr-window-taskbar--top')) ? 'top' : 'bottom';\n }\n\n /**\n * The rail's accessible name — it is a `role=\"toolbar\"`, and an unnamed one is\n * announced as nothing.\n */\n async getRailLabel(): Promise<string | null> {\n return (await this.host()).getAttribute('aria-label');\n }\n\n /** Whether nothing is minimized — the rail draws no markup at all then. */\n async isEmpty(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-window-taskbar__rail')()) === null;\n }\n\n /**\n * The titles in the rail, in order.\n *\n * A window opened without a title still gets a tab, named by the catalog's\n * fallback rather than left blank — a nameless tab is unreachable by voice and\n * indistinguishable from its neighbours.\n */\n async getTabTitles(): Promise<string[]> {\n const titles = await this.locatorForAll('.wr-window-taskbar__tab-title')();\n return Promise.all(titles.map(title => title.text()));\n }\n\n /** A tab's accessible name — the restore wording with the window's title in it. */\n async getRestoreLabel(title: string): Promise<string | null> {\n return (await this.requireTab(title, 'getRestoreLabel')).getAttribute('aria-label');\n }\n\n /** Click a tab — restoring that window and focusing it. */\n async restore(title: string): Promise<void> {\n await (await this.requireTab(title, 'restore')).click();\n }\n\n /**\n * Click a tab's ✕ — closing the window WITHOUT restoring it.\n *\n * Still worth asserting separately now that the two are siblings rather than\n * nested: they sit inside one pill and look like one control, so a close that\n * also restored would flash a closing window's content and look plausible.\n */\n async closeTab(title: string): Promise<void> {\n const index = await this.indexOf(title, 'closeTab');\n const closers = await this.locatorForAll('.wr-window-taskbar__tab-close')();\n await closers[index].click();\n }\n\n /**\n * The tab's BUTTON, not the pill around it.\n *\n * `.wr-window-taskbar__tab` is a plain container — it carries the pill's look\n * and nothing else, because the close beside it cannot be a control nested in\n * a control. The name and the click both belong to `__tab-restore`.\n */\n private async requireTab(title: string, method: string): Promise<TestElement> {\n const tabs = await this.locatorForAll('.wr-window-taskbar__tab-restore')();\n return tabs[await this.indexOf(title, method)];\n }\n\n /** Which tab carries this title — one lookup for both the tab and its close button. */\n private async indexOf(title: string, method: string): Promise<number> {\n const tabs = await this.locatorForAll('.wr-window-taskbar__tab-restore')();\n for (const [index, tab] of tabs.entries()) {\n if ((await tab.text()) === title) return index;\n }\n\n const offered = await this.getTabTitles();\n throw new Error(\n `WrWindowTaskbarHarness.${method}(\"${title}\"): no such tab. The rail holds: ` +\n `${offered.length ? offered.join(', ') : '(nothing — no window is minimized)'}.`\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/fesm2022/ngwr-window.mjs
CHANGED
|
@@ -160,8 +160,8 @@ class WrWindow {
|
|
|
160
160
|
...(ngDevMode ? [{ debugName: "minimizeVisible" }] : /* istanbul ignore next */ []));
|
|
161
161
|
maximizeVisible = computed(() => this.showMaximize() ?? this.resolvedOs() !== 'linux', /* @ts-ignore */
|
|
162
162
|
...(ngDevMode ? [{ debugName: "maximizeVisible" }] : /* istanbul ignore next */ []));
|
|
163
|
-
/** Title-bar density. @default '
|
|
164
|
-
chromeSize = input('
|
|
163
|
+
/** Title-bar density. @default 'md' */
|
|
164
|
+
chromeSize = input('md', /* @ts-ignore */
|
|
165
165
|
...(ngDevMode ? [{ debugName: "chromeSize" }] : /* istanbul ignore next */ []));
|
|
166
166
|
/**
|
|
167
167
|
* Enter / leave animations. Set to `false` to disable the open-fade
|
|
@@ -747,11 +747,11 @@ class WrWindowContainer {
|
|
|
747
747
|
});
|
|
748
748
|
}
|
|
749
749
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrWindowContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
750
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: WrWindowContainer, isStandalone: true, selector: "wr-window-container", viewQueries: [{ propertyName: "contentVcr", first: true, predicate: ["content"], descendants: true, read: ViewContainerRef, isSignal: true }, { propertyName: "wrWindow", first: true, predicate: WrWindow, descendants: true, isSignal: true }], ngImport: i0, template: "<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? '
|
|
750
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: WrWindowContainer, isStandalone: true, selector: "wr-window-container", viewQueries: [{ propertyName: "contentVcr", first: true, predicate: ["content"], descendants: true, read: ViewContainerRef, isSignal: true }, { propertyName: "wrWindow", first: true, predicate: WrWindow, descendants: true, isSignal: true }], ngImport: i0, template: "<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? 'md'\"\n [animations]=\"config.animations ?? true\"\n [initialX]=\"config.x ?? null\"\n [initialY]=\"config.y ?? null\"\n [initialWidth]=\"config.width ?? null\"\n [initialHeight]=\"config.height ?? null\"\n [minWidth]=\"config.minWidth ?? 220\"\n [minHeight]=\"config.minHeight ?? 140\"\n [maxWidth]=\"config.maxWidth ?? 1000000\"\n [maxHeight]=\"config.maxHeight ?? 1000000\"\n [movable]=\"config.movable ?? true\"\n [resizable]=\"config.resizable ?? true\"\n [keepInViewport]=\"config.keepInViewport ?? true\"\n [snap]=\"config.snap ?? 'none'\"\n [dragHandle]=\"config.dragHandle ?? null\"\n [showMinimize]=\"config.showMinimize ?? null\"\n [showMaximize]=\"config.showMaximize ?? null\"\n [showClose]=\"config.showClose ?? true\"\n (closed)=\"ref.close()\"\n #window\n>\n <ng-container #content />\n</wr-window>\n\n@if (window.snapTarget(); as target) {\n <div class=\"wr-window__snap-hint\" [attr.data-target]=\"target\" aria-hidden=\"true\"></div>\n}\n", dependencies: [{ kind: "component", type: WrWindow, selector: "wr-window", inputs: ["open", "state", "title", "initialX", "initialY", "size", "initialWidth", "initialHeight", "os", "chromeSize", "animations", "minWidth", "minHeight", "maxWidth", "maxHeight", "movable", "resizable", "keepInViewport", "snap", "dragHandle", "showMinimize", "showMaximize", "showClose"], outputs: ["openChange", "stateChange", "closed", "moved", "resized"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
751
751
|
}
|
|
752
752
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: WrWindowContainer, decorators: [{
|
|
753
753
|
type: Component,
|
|
754
|
-
args: [{ selector: 'wr-window-container', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [WrWindow], template: "<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? '
|
|
754
|
+
args: [{ selector: 'wr-window-container', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [WrWindow], template: "<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? 'md'\"\n [animations]=\"config.animations ?? true\"\n [initialX]=\"config.x ?? null\"\n [initialY]=\"config.y ?? null\"\n [initialWidth]=\"config.width ?? null\"\n [initialHeight]=\"config.height ?? null\"\n [minWidth]=\"config.minWidth ?? 220\"\n [minHeight]=\"config.minHeight ?? 140\"\n [maxWidth]=\"config.maxWidth ?? 1000000\"\n [maxHeight]=\"config.maxHeight ?? 1000000\"\n [movable]=\"config.movable ?? true\"\n [resizable]=\"config.resizable ?? true\"\n [keepInViewport]=\"config.keepInViewport ?? true\"\n [snap]=\"config.snap ?? 'none'\"\n [dragHandle]=\"config.dragHandle ?? null\"\n [showMinimize]=\"config.showMinimize ?? null\"\n [showMaximize]=\"config.showMaximize ?? null\"\n [showClose]=\"config.showClose ?? true\"\n (closed)=\"ref.close()\"\n #window\n>\n <ng-container #content />\n</wr-window>\n\n@if (window.snapTarget(); as target) {\n <div class=\"wr-window__snap-hint\" [attr.data-target]=\"target\" aria-hidden=\"true\"></div>\n}\n" }]
|
|
755
755
|
}], ctorParameters: () => [], propDecorators: { contentVcr: [{ type: i0.ViewChild, args: ['content', { ...{ read: ViewContainerRef }, isSignal: true }] }], wrWindow: [{ type: i0.ViewChild, args: [i0.forwardRef(() => WrWindow), { isSignal: true }] }] } });
|
|
756
756
|
|
|
757
757
|
/**
|