ngwr 14.0.1 → 14.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/command-palette/styles/_index.scss +17 -0
- package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +82 -5
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +2 -2
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +4 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +1 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +2 -2
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +2 -2
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/i18n/en.json +1 -0
- package/i18n/ru.json +1 -0
- package/package.json +1 -1
- package/schematics/migrations/v9/index.js +11 -3
- package/theme/styles/_focus.scss +23 -2
- package/types/ngwr-command-palette.d.ts +59 -2
- package/types/ngwr-version.d.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-lightbox.mjs","sources":["../../../projects/lib/lightbox/lightbox.ts","../../../projects/lib/lightbox/lightbox.html","../../../projects/lib/lightbox/ngwr-lightbox.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 { type ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { type OverlayRef } from '@angular/cdk/overlay';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport type { TemplateRef } from '@angular/core';\nimport {\n Component,\n DestroyRef,\n ViewContainerRef,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { WR_OVERLAY } from 'ngwr/overlay';\n\nlet viewerUid = 0;\n\n/**\n * Image with click-to-zoom lightbox. The thumbnail is a plain `<img>`\n * with whatever sizing/`object-fit` you give it; clicking opens a CDK\n * overlay showing the full image, with Escape + close button + backdrop\n * to dismiss.\n *\n * @example\n * ```html\n * <wr-lightbox\n * src=\"/photo.jpg\"\n * alt=\"Mountain\"\n * style=\"width: 16rem; height: 10rem; object-fit: cover\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/lightbox\n */\n@Component({\n selector: 'wr-lightbox',\n templateUrl: './lightbox.html',\n styleUrl: './lightbox.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n '[style.aspect-ratio]': 'aspectRatio()',\n },\n})\nexport class WrLightbox {\n /** Accessible name. Falls back to `image.close`, then `'Close preview'`. */\n /** Accessible name of the thumbnail button. Falls back to `alt`, then `image.open`. */\n readonly openLabel = input<string | null>(null);\n\n readonly closeLabel = input<string | null>(null);\n\n protected readonly resolvedCloseLabel = useI18nText(this.closeLabel, 'image.close', 'Close preview');\n\n /** Image source. */\n readonly src = input.required<string>();\n\n /** Alt text. Required for a11y; falls back to an empty string. @default '' */\n readonly alt = input<string>('');\n\n /**\n * Lighter source for the THUMBNAIL — a small or blurred copy, so the grid does not\n * pull full-size images. The viewer always shows `src`; the thumbnail does not swap\n * to it later.\n */\n readonly preview = input<string | null>(null);\n\n // Both of these were hard-coded English literals in the template, next to a catalog\n // that already carried `image.open` translated and unread. `useI18nText` already\n // does the whole chain — a non-empty binding wins, then the catalog, then the\n // English default — so the alt text (which describes the actual picture) is what\n // gets forwarded, with `openLabel` ahead of it as the explicit override.\n protected readonly resolvedOpenLabel = useI18nText(\n computed(() => {\n // Not `??`: an empty `openLabel` is no label at all, so it has to fall through\n // to the alt text rather than winning as an empty string.\n const explicit = this.openLabel();\n if (explicit) return explicit;\n return this.alt();\n }),\n 'image.open',\n 'Open preview'\n );\n\n protected readonly resolvedViewerLabel = useI18nText(this.alt, 'image.viewer', 'Image preview');\n\n /** Disable the click-to-zoom lightbox. @default false */\n readonly disablePreview = input(false, { transform: coerceBooleanProperty });\n\n /** Caption shown under the full image in the lightbox. */\n readonly caption = input<string>('');\n\n /**\n * Reserve space before the image resolves by fixing the thumbnail's\n * `aspect-ratio` (e.g. `'16 / 9'`, `'4 / 3'`, or a number like `1.5`).\n * Prevents the layout jump when the intrinsic image size isn't known up\n * front — pair it with a `width` and the box keeps its height from first\n * paint. @default null\n */\n readonly aspectRatio = input<string | number | null>(null);\n\n protected readonly open = signal(false);\n protected readonly loaded = signal(false);\n\n /**\n * Id the trigger's `aria-controls` points at while the viewer is open.\n *\n * @internal Public so the host bindings can read it.\n */\n protected readonly viewerId = `wr-lightbox-viewer-${++viewerUid}`;\n\n protected readonly classes = computed(() => {\n const parts = ['wr-lightbox'];\n if (this.open()) parts.push('wr-lightbox--open');\n if (!this.loaded()) parts.push('wr-lightbox--loading');\n return parts.join(' ');\n });\n\n // Query by name — `@if` blocks register their own TemplateRefs, so an\n // unqualified TemplateRef query would grab the thumbnail branch instead.\n protected readonly panelTpl = viewChild.required<TemplateRef<unknown>>('viewerTpl');\n\n private readonly overlay = inject(WR_OVERLAY);\n private readonly vcr = inject(ViewContainerRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly focusTrapFactory = inject(ConfigurableFocusTrapFactory);\n private focusTrap: ConfigurableFocusTrap | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private overlayRef: OverlayRef | null = null;\n\n constructor() {\n // Destroying the component while the viewer is open removes the projected\n // content (the portal uses this component's ViewContainerRef) but leaves the\n // overlay pane and its full-screen backdrop behind, with page scroll still\n // blocked. Dispose the overlay explicitly.\n this.destroyRef.onDestroy(() => this.closeOverlay());\n\n effect(() => {\n if (this.open()) this.openOverlay();\n else this.closeOverlay();\n });\n }\n\n protected onClick(): void {\n if (this.disablePreview()) return;\n this.open.set(true);\n }\n\n protected onClose(): void {\n this.open.set(false);\n }\n\n // Swipe-down-to-dismiss on the open viewer. The image follows the finger and\n // fades; releasing past ~20% of the viewer height closes it.\n private viewerStartY = 0;\n private viewerSwiping = false;\n\n protected onViewerSwipeStart(event: TouchEvent): void {\n const touch = event.touches[0];\n if (!touch) return;\n this.viewerStartY = touch.clientY;\n this.viewerSwiping = true;\n }\n\n protected onViewerSwipeMove(event: TouchEvent, viewer: HTMLElement): void {\n if (!this.viewerSwiping) return;\n const touch = event.touches[0];\n if (!touch) return;\n const dy = touch.clientY - this.viewerStartY;\n if (dy <= 0) {\n viewer.style.transform = '';\n viewer.style.opacity = '';\n return;\n }\n event.preventDefault();\n viewer.style.transition = 'none';\n viewer.style.transform = `translateY(${dy}px)`;\n viewer.style.opacity = String(Math.max(0.3, 1 - dy / (viewer.offsetHeight || 1)));\n }\n\n protected onViewerSwipeEnd(event: TouchEvent, viewer: HTMLElement): void {\n if (!this.viewerSwiping) return;\n this.viewerSwiping = false;\n const touch = event.changedTouches[0];\n const dy = touch ? touch.clientY - this.viewerStartY : 0;\n if (dy > (viewer.offsetHeight || 0) * 0.2) {\n this.onClose();\n } else {\n viewer.style.transition = '';\n viewer.style.transform = '';\n viewer.style.opacity = '';\n }\n }\n\n /**\n * The thumbnail has settled, one way or the other. A failure counts: `--loading`\n * animates a shimmer AND sets `opacity: 0` on the image, so a broken `src` with no\n * error path left an invisible box shimmering for ever instead of showing its alt\n * text.\n */\n protected onSettled(): void {\n this.loaded.set(true);\n }\n\n // Overlay\n\n private openOverlay(): void {\n if (this.overlayRef) return;\n\n this.overlayRef = this.overlay.create({\n hasBackdrop: true,\n backdropClass: 'wr-lightbox-backdrop',\n positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(),\n scrollStrategy: this.overlay.scrollStrategies.block(),\n panelClass: 'wr-lightbox-overlay',\n });\n\n const portal = new TemplatePortal(this.panelTpl(), this.vcr);\n this.overlayRef.attach(portal);\n\n // The viewer declares role=\"dialog\" + aria-modal=\"true\", which promises the\n // rest of the page is inert. Without a focus trap that promise is a lie:\n // Tab walks straight out of the viewer into the page behind the backdrop.\n const active = document.activeElement;\n this.previouslyFocused = active instanceof HTMLElement ? active : null;\n this.focusTrap = this.focusTrapFactory.create(this.overlayRef.overlayElement);\n void this.focusTrap.focusInitialElementWhenReady();\n\n this.overlayRef\n .backdropClick()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.open.set(false));\n\n this.overlayRef\n .keydownEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.open.set(false);\n }\n });\n }\n\n private closeOverlay(): void {\n if (!this.overlayRef) return;\n this.focusTrap?.destroy();\n this.focusTrap = null;\n const restore = this.previouslyFocused;\n this.previouslyFocused = null;\n this.overlayRef.dispose();\n this.overlayRef = null;\n // Send focus back where it came from, or it lands on <body> and the user\n // has to tab from the top of the page again.\n if (restore && typeof restore.focus === 'function') restore.focus();\n }\n}\n","@if (disablePreview()) {\n <img\n class=\"wr-lightbox__thumb\"\n [src]=\"preview() || src()\"\n [alt]=\"alt()\"\n (load)=\"onSettled()\"\n (error)=\"onSettled()\"\n loading=\"lazy\"\n decoding=\"async\"\n />\n} @else {\n <!-- The trigger opens a modal dialog, and used to say so nowhere: no hint that it\n opens anything, and nothing on the page tying it to the viewer it opened. -->\n <button\n type=\"button\"\n class=\"wr-lightbox__trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-controls]=\"open() ? viewerId : null\"\n [attr.aria-label]=\"resolvedOpenLabel()\"\n (click)=\"onClick()\"\n >\n <img\n class=\"wr-lightbox__thumb\"\n [src]=\"preview() || src()\"\n [alt]=\"alt()\"\n (load)=\"onSettled()\"\n (error)=\"onSettled()\"\n loading=\"lazy\"\n decoding=\"async\"\n />\n </button>\n}\n\n<ng-template #viewerTpl>\n <div\n #viewer\n class=\"wr-lightbox-viewer\"\n [id]=\"viewerId\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"resolvedViewerLabel()\"\n (touchstart)=\"onViewerSwipeStart($event)\"\n (touchmove)=\"onViewerSwipeMove($event, viewer)\"\n (touchend)=\"onViewerSwipeEnd($event, viewer)\"\n (touchcancel)=\"onViewerSwipeEnd($event, viewer)\"\n >\n <button\n type=\"button\"\n class=\"wr-lightbox-viewer__close\"\n [attr.aria-label]=\"resolvedCloseLabel()\"\n (click)=\"onClose()\"\n (keydown.enter)=\"onClose()\"\n (keydown.space)=\"onClose()\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n <!--\n Styled `cursor: zoom-out`, which is a promise: clicking the image closes. A\n REDUNDANT mouse affordance — the close button, Escape, the backdrop and\n swipe-down all do the same thing and all reach a keyboard — so the image stays\n out of the tab order rather than becoming a second close stop.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <img class=\"wr-lightbox-viewer__full\" [src]=\"src()\" [alt]=\"alt()\" (click)=\"onClose()\" />\n @if (caption()) {\n <div class=\"wr-lightbox-viewer__caption\">{{ caption() }}</div>\n }\n </div>\n</ng-template>\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-lightbox.mjs","sources":["../../../projects/lib/lightbox/lightbox.ts","../../../projects/lib/lightbox/lightbox.html","../../../projects/lib/lightbox/ngwr-lightbox.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 { type ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { type OverlayRef } from '@angular/cdk/overlay';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport type { TemplateRef } from '@angular/core';\nimport {\n Component,\n DestroyRef,\n ViewContainerRef,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { WR_OVERLAY } from 'ngwr/overlay';\n\nlet viewerUid = 0;\n\n/**\n * Image with click-to-zoom lightbox. The thumbnail is a plain `<img>`\n * with whatever sizing/`object-fit` you give it; clicking opens a CDK\n * overlay showing the full image, with Escape + close button + backdrop\n * to dismiss.\n *\n * @example\n * ```html\n * <wr-lightbox\n * src=\"/photo.jpg\"\n * alt=\"Mountain\"\n * style=\"width: 16rem; height: 10rem; object-fit: cover\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/lightbox\n */\n@Component({\n selector: 'wr-lightbox',\n templateUrl: './lightbox.html',\n styleUrl: './lightbox.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n '[style.aspect-ratio]': 'aspectRatio()',\n },\n})\nexport class WrLightbox {\n /** Accessible name. Falls back to `image.close`, then `'Close preview'`. */\n /** Accessible name of the thumbnail button. Falls back to `alt`, then `image.open`. */\n readonly openLabel = input<string | null>(null);\n\n readonly closeLabel = input<string | null>(null);\n\n protected readonly resolvedCloseLabel = useI18nText(this.closeLabel, 'image.close', 'Close preview');\n\n /** Image source. */\n readonly src = input.required<string>();\n\n /** Alt text. Required for a11y; falls back to an empty string. @default '' */\n readonly alt = input<string>('');\n\n /**\n * Lighter source for the THUMBNAIL — a small or blurred copy, so the grid does not\n * pull full-size images. The viewer always shows `src`; the thumbnail does not swap\n * to it later.\n */\n readonly preview = input<string | null>(null);\n\n // Both of these were hard-coded English literals in the template, next to a catalog\n // that already carried `image.open` translated and unread. `useI18nText` already\n // does the whole chain — a non-empty binding wins, then the catalog, then the\n // English default — so the alt text (which describes the actual picture) is what\n // gets forwarded, with `openLabel` ahead of it as the explicit override.\n protected readonly resolvedOpenLabel = useI18nText(\n computed(() => {\n // Not `??`: an empty `openLabel` is no label at all, so it has to fall through\n // to the alt text rather than winning as an empty string.\n const explicit = this.openLabel();\n if (explicit) return explicit;\n return this.alt();\n }),\n 'image.open',\n 'Open preview'\n );\n\n protected readonly resolvedViewerLabel = useI18nText(this.alt, 'image.viewer', 'Image preview');\n\n /** Disable the click-to-zoom lightbox. @default false */\n readonly disablePreview = input(false, { transform: coerceBooleanProperty });\n\n /** Caption shown under the full image in the lightbox. */\n readonly caption = input<string>('');\n\n /**\n * Reserve space before the image resolves by fixing the thumbnail's\n * `aspect-ratio` (e.g. `'16 / 9'`, `'4 / 3'`, or a number like `1.5`).\n * Prevents the layout jump when the intrinsic image size isn't known up\n * front — pair it with a `width` and the box keeps its height from first\n * paint. @default null\n */\n readonly aspectRatio = input<string | number | null>(null);\n\n protected readonly open = signal(false);\n protected readonly loaded = signal(false);\n\n /**\n * Id the trigger's `aria-controls` points at while the viewer is open.\n *\n * @internal Public so the host bindings can read it.\n */\n protected readonly viewerId = `wr-lightbox-viewer-${++viewerUid}`;\n\n protected readonly classes = computed(() => {\n const parts = ['wr-lightbox'];\n if (this.open()) parts.push('wr-lightbox--open');\n if (!this.loaded()) parts.push('wr-lightbox--loading');\n return parts.join(' ');\n });\n\n // Query by name — `@if` blocks register their own TemplateRefs, so an\n // unqualified TemplateRef query would grab the thumbnail branch instead.\n protected readonly panelTpl = viewChild.required<TemplateRef<unknown>>('viewerTpl');\n\n private readonly overlay = inject(WR_OVERLAY);\n private readonly vcr = inject(ViewContainerRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly focusTrapFactory = inject(ConfigurableFocusTrapFactory);\n private focusTrap: ConfigurableFocusTrap | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private overlayRef: OverlayRef | null = null;\n\n constructor() {\n // Destroying the component while the viewer is open removes the projected\n // content (the portal uses this component's ViewContainerRef) but leaves the\n // overlay pane and its full-screen backdrop behind, with page scroll still\n // blocked. Dispose the overlay explicitly.\n this.destroyRef.onDestroy(() => this.closeOverlay());\n\n effect(() => {\n if (this.open()) this.openOverlay();\n else this.closeOverlay();\n });\n }\n\n protected onClick(): void {\n if (this.disablePreview()) return;\n this.open.set(true);\n }\n\n protected onClose(): void {\n this.open.set(false);\n }\n\n // Swipe-down-to-dismiss on the open viewer. The image follows the finger and\n // fades; releasing past ~20% of the viewer height closes it.\n private viewerStartY = 0;\n private viewerSwiping = false;\n\n protected onViewerSwipeStart(event: TouchEvent): void {\n const touch = event.touches[0];\n if (!touch) return;\n this.viewerStartY = touch.clientY;\n this.viewerSwiping = true;\n }\n\n protected onViewerSwipeMove(event: TouchEvent, viewer: HTMLElement): void {\n if (!this.viewerSwiping) return;\n const touch = event.touches[0];\n if (!touch) return;\n const dy = touch.clientY - this.viewerStartY;\n if (dy <= 0) {\n viewer.style.transform = '';\n viewer.style.opacity = '';\n return;\n }\n event.preventDefault();\n viewer.style.transition = 'none';\n viewer.style.transform = `translateY(${dy}px)`;\n viewer.style.opacity = String(Math.max(0.3, 1 - dy / (viewer.offsetHeight || 1)));\n }\n\n protected onViewerSwipeEnd(event: TouchEvent, viewer: HTMLElement): void {\n if (!this.viewerSwiping) return;\n this.viewerSwiping = false;\n const touch = event.changedTouches[0];\n const dy = touch ? touch.clientY - this.viewerStartY : 0;\n if (dy > (viewer.offsetHeight || 0) * 0.2) {\n this.onClose();\n } else {\n viewer.style.transition = '';\n viewer.style.transform = '';\n viewer.style.opacity = '';\n }\n }\n\n /**\n * The thumbnail has settled, one way or the other. A failure counts: `--loading`\n * animates a shimmer AND sets `opacity: 0` on the image, so a broken `src` with no\n * error path left an invisible box shimmering for ever instead of showing its alt\n * text.\n */\n protected onSettled(): void {\n this.loaded.set(true);\n }\n\n // Overlay\n\n private openOverlay(): void {\n if (this.overlayRef) return;\n\n this.overlayRef = this.overlay.create({\n hasBackdrop: true,\n backdropClass: 'wr-lightbox-backdrop',\n positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(),\n scrollStrategy: this.overlay.scrollStrategies.block(),\n panelClass: 'wr-lightbox-overlay',\n });\n\n const portal = new TemplatePortal(this.panelTpl(), this.vcr);\n this.overlayRef.attach(portal);\n\n // The viewer declares role=\"dialog\" + aria-modal=\"true\", which promises the\n // rest of the page is inert. Without a focus trap that promise is a lie:\n // Tab walks straight out of the viewer into the page behind the backdrop.\n const active = document.activeElement;\n this.previouslyFocused = active instanceof HTMLElement ? active : null;\n this.focusTrap = this.focusTrapFactory.create(this.overlayRef.overlayElement);\n void this.focusTrap.focusInitialElementWhenReady();\n\n this.overlayRef\n .backdropClick()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.open.set(false));\n\n this.overlayRef\n .keydownEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.open.set(false);\n }\n });\n }\n\n private closeOverlay(): void {\n if (!this.overlayRef) return;\n this.focusTrap?.destroy();\n this.focusTrap = null;\n const restore = this.previouslyFocused;\n this.previouslyFocused = null;\n this.overlayRef.dispose();\n this.overlayRef = null;\n // Send focus back where it came from, or it lands on <body> and the user\n // has to tab from the top of the page again.\n if (restore && typeof restore.focus === 'function') restore.focus();\n }\n}\n","@if (disablePreview()) {\n <img\n class=\"wr-lightbox__thumb\"\n [src]=\"preview() || src()\"\n [alt]=\"alt()\"\n (load)=\"onSettled()\"\n (error)=\"onSettled()\"\n loading=\"lazy\"\n decoding=\"async\"\n />\n} @else {\n <!-- The trigger opens a modal dialog, and used to say so nowhere: no hint that it\n opens anything, and nothing on the page tying it to the viewer it opened. -->\n <button\n type=\"button\"\n class=\"wr-lightbox__trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-controls]=\"open() ? viewerId : null\"\n [attr.aria-label]=\"resolvedOpenLabel()\"\n (click)=\"onClick()\"\n >\n <img\n class=\"wr-lightbox__thumb\"\n [src]=\"preview() || src()\"\n [alt]=\"alt()\"\n (load)=\"onSettled()\"\n (error)=\"onSettled()\"\n loading=\"lazy\"\n decoding=\"async\"\n />\n </button>\n}\n\n<ng-template #viewerTpl>\n <div\n #viewer\n class=\"wr-lightbox-viewer\"\n [id]=\"viewerId\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"resolvedViewerLabel()\"\n (touchstart)=\"onViewerSwipeStart($event)\"\n (touchmove)=\"onViewerSwipeMove($event, viewer)\"\n (touchend)=\"onViewerSwipeEnd($event, viewer)\"\n (touchcancel)=\"onViewerSwipeEnd($event, viewer)\"\n >\n <button\n type=\"button\"\n class=\"wr-lightbox-viewer__close\"\n [attr.aria-label]=\"resolvedCloseLabel()\"\n (click)=\"onClose()\"\n (keydown.enter)=\"onClose()\"\n (keydown.space)=\"onClose()\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n <!--\n Styled `cursor: zoom-out`, which is a promise: clicking the image closes. A\n REDUNDANT mouse affordance — the close button, Escape, the backdrop and\n swipe-down all do the same thing and all reach a keyboard — so the image stays\n out of the tab order rather than becoming a second close stop.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <img class=\"wr-lightbox-viewer__full\" [src]=\"src()\" [alt]=\"alt()\" (click)=\"onClose()\" />\n @if (caption()) {\n <div class=\"wr-lightbox-viewer__caption\">{{ caption() }}</div>\n }\n </div>\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/fesm2022/ngwr-list.mjs
CHANGED
|
@@ -52,14 +52,14 @@ class WrList {
|
|
|
52
52
|
}, /* @ts-ignore */
|
|
53
53
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
54
54
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
55
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: WrList, isStandalone: true, selector: "wr-list", inputs: { bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, dividers: { classPropertyName: "dividers", publicName: "dividers", isSignal: true, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.aria-label": "ariaLabel() || null" } }, ngImport: i0, template: '<ul class="wr-list__items" role="list"><ng-content /></ul>', isInline: true, styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible
|
|
55
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: WrList, isStandalone: true, selector: "wr-list", inputs: { bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, dividers: { classPropertyName: "dividers", publicName: "dividers", isSignal: true, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.aria-label": "ariaLabel() || null" } }, ngImport: i0, template: '<ul class="wr-list__items" role="list"><ng-content /></ul>', isInline: true, styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-mention-panel__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-segmented__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-back-top:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-stepper__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-window__chrome-action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-dropdown-item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-alert__close:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-list{--wr-list-item-padding-y: .625rem;--wr-list-item-padding-x: 1rem;--wr-list-item-gap: .75rem;--wr-list-divider-color: var(--wr-color-outline);--wr-list-bg: transparent;--wr-list-hover-bg: var(--wr-color-hover);--wr-list-active-bg: rgba(var(--wr-color-primary-rgb), .08);display:block;font-family:var(--wr-font-family-base);font-size:var(--wr-text-sm);color:var(--wr-color-on-surface);background:var(--wr-list-bg)}.wr-list__items{list-style:none;margin:0;padding:0}.wr-list--bordered{border:1px solid var(--wr-list-divider-color);border-radius:var(--wr-border-radius-base)}@supports (corner-shape: squircle){.wr-list--bordered{corner-shape:squircle;border-radius:calc(var(--wr-border-radius-base) * 1.85)}}.wr-list--bordered{overflow:hidden}.wr-list--dividers .wr-list__item:not(:last-child){border-bottom:1px solid var(--wr-list-divider-color)}.wr-list--dense{--wr-list-item-padding-y: .375rem}.wr-list__item{display:flex;align-items:center;gap:var(--wr-list-item-gap);padding:calc(var(--wr-list-item-padding-y) * var(--wr-density-y, 1)) calc(var(--wr-list-item-padding-x) * var(--wr-density-x, 1));color:inherit;transition:background .12s ease}.wr-list__item--interactive{cursor:pointer}.wr-list__item--interactive:hover{background:var(--wr-list-hover-bg)}.wr-list__item--interactive:active{background:var(--wr-list-active-bg)}.wr-list__item--interactive:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-list__item--disabled{opacity:var(--wr-disabled-opacity);pointer-events:none;cursor:not-allowed}.wr-list__leading,.wr-list__trailing{display:inline-flex;align-items:center;flex:0 0 auto;color:rgba(var(--wr-color-on-surface-rgb),.65)}.wr-list__leading:empty,.wr-list__trailing:empty{display:none}.wr-list__body{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], encapsulation: i0.ViewEncapsulation.None });
|
|
56
56
|
}
|
|
57
57
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrList, decorators: [{
|
|
58
58
|
type: Component,
|
|
59
59
|
args: [{ selector: 'wr-list', template: '<ul class="wr-list__items" role="list"><ng-content /></ul>', encapsulation: ViewEncapsulation.None, host: {
|
|
60
60
|
'[class]': 'classes()',
|
|
61
61
|
'[attr.aria-label]': 'ariaLabel() || null',
|
|
62
|
-
}, styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible
|
|
62
|
+
}, styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-mention-panel__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-segmented__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-back-top:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-stepper__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-window__chrome-action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-dropdown-item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-alert__close:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-list{--wr-list-item-padding-y: .625rem;--wr-list-item-padding-x: 1rem;--wr-list-item-gap: .75rem;--wr-list-divider-color: var(--wr-color-outline);--wr-list-bg: transparent;--wr-list-hover-bg: var(--wr-color-hover);--wr-list-active-bg: rgba(var(--wr-color-primary-rgb), .08);display:block;font-family:var(--wr-font-family-base);font-size:var(--wr-text-sm);color:var(--wr-color-on-surface);background:var(--wr-list-bg)}.wr-list__items{list-style:none;margin:0;padding:0}.wr-list--bordered{border:1px solid var(--wr-list-divider-color);border-radius:var(--wr-border-radius-base)}@supports (corner-shape: squircle){.wr-list--bordered{corner-shape:squircle;border-radius:calc(var(--wr-border-radius-base) * 1.85)}}.wr-list--bordered{overflow:hidden}.wr-list--dividers .wr-list__item:not(:last-child){border-bottom:1px solid var(--wr-list-divider-color)}.wr-list--dense{--wr-list-item-padding-y: .375rem}.wr-list__item{display:flex;align-items:center;gap:var(--wr-list-item-gap);padding:calc(var(--wr-list-item-padding-y) * var(--wr-density-y, 1)) calc(var(--wr-list-item-padding-x) * var(--wr-density-x, 1));color:inherit;transition:background .12s ease}.wr-list__item--interactive{cursor:pointer}.wr-list__item--interactive:hover{background:var(--wr-list-hover-bg)}.wr-list__item--interactive:active{background:var(--wr-list-active-bg)}.wr-list__item--interactive:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-list__item--disabled{opacity:var(--wr-disabled-opacity);pointer-events:none;cursor:not-allowed}.wr-list__leading,.wr-list__trailing{display:inline-flex;align-items:center;flex:0 0 auto;color:rgba(var(--wr-color-on-surface-rgb),.65)}.wr-list__leading:empty,.wr-list__trailing:empty{display:none}.wr-list__body{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"] }]
|
|
63
63
|
}], propDecorators: { bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], dividers: [{ type: i0.Input, args: [{ isSignal: true, alias: "dividers", required: false }] }], dense: [{ type: i0.Input, args: [{ isSignal: true, alias: "dense", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
64
64
|
|
|
65
65
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-list.mjs","sources":["../../../projects/lib/list/list.ts","../../../projects/lib/list/list-item.ts","../../../projects/lib/list/list-item.html","../../../projects/lib/list/ngwr-list.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 { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\n/**\n * Generic list container. Renders `<ul role=\"list\">` with optional\n * borders, dividers between items, and dense (compact) padding. Project\n * `<wr-list-item>` children — they pick up the container's settings\n * through CSS cascade, no DI needed.\n *\n * @example\n * ```html\n * <wr-list bordered dividers>\n * <wr-list-item>\n * <wr-icon ngProjectAs=\"[wrListItemLeading]\" name=\"folder\" />\n * Reports\n * <span ngProjectAs=\"[wrListItemTrailing]\">12</span>\n * </wr-list-item>\n * <wr-list-item interactive (click)=\"open(item)\">\n * Click anywhere on this row\n * </wr-list-item>\n * </wr-list>\n * ```\n *\n * @see https://ngwr.dev/reference/components/list\n */\n@Component({\n selector: 'wr-list',\n template: '<ul class=\"wr-list__items\" role=\"list\"><ng-content /></ul>',\n styleUrl: './list.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n '[attr.aria-label]': 'ariaLabel() || null',\n },\n})\nexport class WrList {\n /** Wrap the list in a card-style border + radius. @default false */\n readonly bordered = input(false, { transform: coerceBooleanProperty });\n\n /** Draw a thin divider between items. @default false */\n readonly dividers = input(false, { transform: coerceBooleanProperty });\n\n /** Use compact padding on every item. @default false */\n readonly dense = input(false, { transform: coerceBooleanProperty });\n\n /** Optional accessible label for the list. */\n readonly ariaLabel = input<string>('');\n\n protected readonly classes = computed(() => {\n const parts = ['wr-list'];\n if (this.bordered()) parts.push('wr-list--bordered');\n if (this.dividers()) parts.push('wr-list--dividers');\n if (this.dense()) parts.push('wr-list--dense');\n return parts.join(' ');\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 { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\n/**\n * Row inside `<wr-list>`. Three projection slots:\n *\n * - `[wrListItemLeading]` — icon, avatar, status dot, etc.\n * - default — main label / body\n * - `[wrListItemTrailing]` — meta value, action button, chevron\n *\n * Set `interactive` to get hover and cursor styles, a tab stop, and Enter /\n * Space activation. The role stays `listitem`: the row lives inside a\n * `<ul role=\"list\">`, where a `button` or `option` child role would break the\n * structure the container promises. That means an interactive row ANNOUNCES as\n * a list item rather than as a control — deliberate, but worth knowing when the\n * whole row is the only way to reach an action. Where the action needs to be\n * announced as one, project a real button into `[wrListItemTrailing]`.\n *\n * @example\n * ```html\n * <wr-list-item>Plain row</wr-list-item>\n *\n * <wr-list-item interactive (click)=\"onPick(item)\">\n * <wr-icon ngProjectAs=\"[wrListItemLeading]\" name=\"folder\" />\n * Reports\n * <span ngProjectAs=\"[wrListItemTrailing]\">12</span>\n * </wr-list-item>\n * ```\n */\n@Component({\n selector: 'wr-list-item',\n templateUrl: './list-item.html',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n role: 'listitem',\n '[attr.tabindex]': 'interactive() ? \"0\" : null',\n '[attr.aria-disabled]': 'disabled() || null',\n '(keydown.enter)': 'onActivate($event)',\n '(keydown.space)': 'onActivate($event)',\n },\n})\nexport class WrListItem {\n /** Adds hover / cursor styles + keyboard activation. @default false */\n readonly interactive = input(false, { transform: coerceBooleanProperty });\n\n /** Visual disabled state. Suppresses hover + keyboard activation. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-list__item'];\n if (this.interactive()) parts.push('wr-list__item--interactive');\n if (this.disabled()) parts.push('wr-list__item--disabled');\n return parts.join(' ');\n });\n\n protected onActivate(event: Event): void {\n if (!this.interactive() || this.disabled()) return;\n event.preventDefault();\n (event.currentTarget as HTMLElement).click();\n }\n}\n","<span class=\"wr-list__leading\"><ng-content select=\"[wrListItemLeading]\" /></span>\n<span class=\"wr-list__body\"><ng-content /></span>\n<span class=\"wr-list__trailing\"><ng-content select=\"[wrListItemTrailing]\" /></span>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAAA;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;AAqBG;MAWU,MAAM,CAAA;;IAER,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG7D,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG7D,KAAK,GAAG,KAAK,CAAC,KAAK,6EAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG1D,SAAS,GAAG,KAAK,CAAS,EAAE;kFAAC;AAEnB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC;QACzB,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;QACpD,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;QACpD,IAAI,IAAI,CAAC,KAAK,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC;AAC9C,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,CAAC;gFAAC;uGAnBS,MAAM,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAN,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAM,uqBARP,4DAA4D,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,
|
|
1
|
+
{"version":3,"file":"ngwr-list.mjs","sources":["../../../projects/lib/list/list.ts","../../../projects/lib/list/list-item.ts","../../../projects/lib/list/list-item.html","../../../projects/lib/list/ngwr-list.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 { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\n/**\n * Generic list container. Renders `<ul role=\"list\">` with optional\n * borders, dividers between items, and dense (compact) padding. Project\n * `<wr-list-item>` children — they pick up the container's settings\n * through CSS cascade, no DI needed.\n *\n * @example\n * ```html\n * <wr-list bordered dividers>\n * <wr-list-item>\n * <wr-icon ngProjectAs=\"[wrListItemLeading]\" name=\"folder\" />\n * Reports\n * <span ngProjectAs=\"[wrListItemTrailing]\">12</span>\n * </wr-list-item>\n * <wr-list-item interactive (click)=\"open(item)\">\n * Click anywhere on this row\n * </wr-list-item>\n * </wr-list>\n * ```\n *\n * @see https://ngwr.dev/reference/components/list\n */\n@Component({\n selector: 'wr-list',\n template: '<ul class=\"wr-list__items\" role=\"list\"><ng-content /></ul>',\n styleUrl: './list.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n '[attr.aria-label]': 'ariaLabel() || null',\n },\n})\nexport class WrList {\n /** Wrap the list in a card-style border + radius. @default false */\n readonly bordered = input(false, { transform: coerceBooleanProperty });\n\n /** Draw a thin divider between items. @default false */\n readonly dividers = input(false, { transform: coerceBooleanProperty });\n\n /** Use compact padding on every item. @default false */\n readonly dense = input(false, { transform: coerceBooleanProperty });\n\n /** Optional accessible label for the list. */\n readonly ariaLabel = input<string>('');\n\n protected readonly classes = computed(() => {\n const parts = ['wr-list'];\n if (this.bordered()) parts.push('wr-list--bordered');\n if (this.dividers()) parts.push('wr-list--dividers');\n if (this.dense()) parts.push('wr-list--dense');\n return parts.join(' ');\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 { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\n/**\n * Row inside `<wr-list>`. Three projection slots:\n *\n * - `[wrListItemLeading]` — icon, avatar, status dot, etc.\n * - default — main label / body\n * - `[wrListItemTrailing]` — meta value, action button, chevron\n *\n * Set `interactive` to get hover and cursor styles, a tab stop, and Enter /\n * Space activation. The role stays `listitem`: the row lives inside a\n * `<ul role=\"list\">`, where a `button` or `option` child role would break the\n * structure the container promises. That means an interactive row ANNOUNCES as\n * a list item rather than as a control — deliberate, but worth knowing when the\n * whole row is the only way to reach an action. Where the action needs to be\n * announced as one, project a real button into `[wrListItemTrailing]`.\n *\n * @example\n * ```html\n * <wr-list-item>Plain row</wr-list-item>\n *\n * <wr-list-item interactive (click)=\"onPick(item)\">\n * <wr-icon ngProjectAs=\"[wrListItemLeading]\" name=\"folder\" />\n * Reports\n * <span ngProjectAs=\"[wrListItemTrailing]\">12</span>\n * </wr-list-item>\n * ```\n */\n@Component({\n selector: 'wr-list-item',\n templateUrl: './list-item.html',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n role: 'listitem',\n '[attr.tabindex]': 'interactive() ? \"0\" : null',\n '[attr.aria-disabled]': 'disabled() || null',\n '(keydown.enter)': 'onActivate($event)',\n '(keydown.space)': 'onActivate($event)',\n },\n})\nexport class WrListItem {\n /** Adds hover / cursor styles + keyboard activation. @default false */\n readonly interactive = input(false, { transform: coerceBooleanProperty });\n\n /** Visual disabled state. Suppresses hover + keyboard activation. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-list__item'];\n if (this.interactive()) parts.push('wr-list__item--interactive');\n if (this.disabled()) parts.push('wr-list__item--disabled');\n return parts.join(' ');\n });\n\n protected onActivate(event: Event): void {\n if (!this.interactive() || this.disabled()) return;\n event.preventDefault();\n (event.currentTarget as HTMLElement).click();\n }\n}\n","<span class=\"wr-list__leading\"><ng-content select=\"[wrListItemLeading]\" /></span>\n<span class=\"wr-list__body\"><ng-content /></span>\n<span class=\"wr-list__trailing\"><ng-content select=\"[wrListItemTrailing]\" /></span>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAAA;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;AAqBG;MAWU,MAAM,CAAA;;IAER,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG7D,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG7D,KAAK,GAAG,KAAK,CAAC,KAAK,6EAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG1D,SAAS,GAAG,KAAK,CAAS,EAAE;kFAAC;AAEnB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC;QACzB,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;QACpD,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;QACpD,IAAI,IAAI,CAAC,KAAK,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC;AAC9C,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,CAAC;gFAAC;uGAnBS,MAAM,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAN,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAM,uqBARP,4DAA4D,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,o7LAAA,CAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAQ3D,MAAM,EAAA,UAAA,EAAA,CAAA;kBAVlB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,SAAS,YACT,4DAA4D,EAAA,aAAA,EAEvD,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,SAAS,EAAE,WAAW;AACtB,wBAAA,mBAAmB,EAAE,qBAAqB;AAC3C,qBAAA,EAAA,MAAA,EAAA,CAAA,o7LAAA,CAAA,EAAA;;;ACxCH;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;MAcU,UAAU,CAAA;;IAEZ,WAAW,GAAG,KAAK,CAAC,KAAK,mFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAGhE,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;AAEnD,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,CAAC,eAAe,CAAC;QAC/B,IAAI,IAAI,CAAC,WAAW,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC;QAChE,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC;AAC1D,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,CAAC;gFAAC;AAEQ,IAAA,UAAU,CAAC,KAAY,EAAA;QAC/B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QAC5C,KAAK,CAAC,cAAc,EAAE;AACrB,QAAA,KAAK,CAAC,aAA6B,CAAC,KAAK,EAAE;IAC9C;uGAlBW,UAAU,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAV,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAU,6mBCjDvB,uOAGA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FD8Ca,UAAU,EAAA,UAAA,EAAA,CAAA;kBAbtB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,cAAc,EAAA,aAAA,EAET,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,SAAS,EAAE,WAAW;AACtB,wBAAA,IAAI,EAAE,UAAU;AAChB,wBAAA,iBAAiB,EAAE,4BAA4B;AAC/C,wBAAA,sBAAsB,EAAE,oBAAoB;AAC5C,wBAAA,iBAAiB,EAAE,oBAAoB;AACvC,wBAAA,iBAAiB,EAAE,oBAAoB;AACxC,qBAAA,EAAA,QAAA,EAAA,uOAAA,EAAA;;;AE/CH;;AAEG;;;;"}
|
|
@@ -16,7 +16,7 @@ import { InjectionToken } from '@angular/core';
|
|
|
16
16
|
* Distinct from `Version` exported by `@angular/core`, which reports the
|
|
17
17
|
* loaded Angular runtime version (e.g. `'22.0.0'`), not ngwr's.
|
|
18
18
|
*/
|
|
19
|
-
const NGWR_VERSION = '14.0
|
|
19
|
+
const NGWR_VERSION = '14.2.0';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @license
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-version.mjs","sources":["../../../projects/lib/version/version.ts","../../../projects/lib/version/version.token.ts","../../../projects/lib/version/ngwr-version.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\n/**\n * The ngwr library version string, kept in sync with\n * `projects/lib/package.json` by `scripts/release-prepare.ts`.\n *\n * Prefer this over reading `package.json` at runtime — that requires a JSON\n * import or `require`, neither of which tree-shakes well in Angular builds.\n *\n * Distinct from `Version` exported by `@angular/core`, which reports the\n * loaded Angular runtime version (e.g. `'22.0.0'`), not ngwr's.\n */\nexport const NGWR_VERSION = '14.0
|
|
1
|
+
{"version":3,"file":"ngwr-version.mjs","sources":["../../../projects/lib/version/version.ts","../../../projects/lib/version/version.token.ts","../../../projects/lib/version/ngwr-version.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\n/**\n * The ngwr library version string, kept in sync with\n * `projects/lib/package.json` by `scripts/release-prepare.ts`.\n *\n * Prefer this over reading `package.json` at runtime — that requires a JSON\n * import or `require`, neither of which tree-shakes well in Angular builds.\n *\n * Distinct from `Version` exported by `@angular/core`, which reports the\n * loaded Angular runtime version (e.g. `'22.0.0'`), not ngwr's.\n */\nexport const NGWR_VERSION = '14.2.0';\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 { InjectionToken } from '@angular/core';\n\nimport { NGWR_VERSION } from './version';\n\n/**\n * Injection token holding the ngwr library version string.\n *\n * Default factory returns {@link NGWR_VERSION}. Override it in tests or in\n * apps that want to surface a custom build identifier.\n *\n * @example\n * ```ts\n * @Component({...})\n * export class FooterComponent {\n * readonly version = inject(NGWR_VERSION_TOKEN);\n * }\n * ```\n */\nexport const NGWR_VERSION_TOKEN = new InjectionToken<string>('NGWR_VERSION_TOKEN', {\n providedIn: 'root',\n factory: () => NGWR_VERSION,\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAEH;;;;;;;;;AASG;AACI,MAAM,YAAY,GAAG;;ACjB5B;;;;;AAKG;AAMH;;;;;;;;;;;;;AAaG;MACU,kBAAkB,GAAG,IAAI,cAAc,CAAS,oBAAoB,EAAE;AACjF,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,YAAY;AAC5B,CAAA;;AC5BD;;AAEG;;;;"}
|
package/i18n/en.json
CHANGED
package/i18n/ru.json
CHANGED
package/package.json
CHANGED
|
@@ -8,15 +8,23 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
/**
|
|
10
10
|
* Match `value` / `[value]` / `[(value)]` inside a `<wr-checkbox …>` open tag.
|
|
11
|
-
* `[^>]*?` stays inside the tag (it can't cross `>`), so the rename never
|
|
12
|
-
* escapes the element it's scoped to.
|
|
13
11
|
*
|
|
14
12
|
* The tag anchor is `(?![-\w])`, NOT `\b`: a word boundary still matches at
|
|
15
13
|
* `<wr-checkbox-group`, whose own `value` IS its form model (it is the group's
|
|
16
14
|
* `FormValueControl`) and must be left alone — renaming it would break every
|
|
17
15
|
* bound group.
|
|
16
|
+
*
|
|
17
|
+
* Quoted values are STEPPED OVER rather than excluded, and that is the half a
|
|
18
|
+
* plain `[^>]*?` got wrong for two majors: a `>` inside a binding expression
|
|
19
|
+
* looks like the end of the tag, so `<wr-checkbox [disabled]="n > 0" value="a">`
|
|
20
|
+
* kept its `value` while the same attributes in the other order moved. The
|
|
21
|
+
* leftover is SILENT — a static `value="a"` that matches no input is an ordinary
|
|
22
|
+
* DOM attribute, `strictTemplates` says nothing, and every checkbox in the group
|
|
23
|
+
* keeps the default identity `null`, so they all toggle together. That is the
|
|
24
|
+
* exact defect this migration exists to prevent, reintroduced by the migration
|
|
25
|
+
* itself. `migration-v14` fixed the same anchoring; this is that fix, ported.
|
|
18
26
|
*/
|
|
19
|
-
const CHECKBOX_TAG = String.raw `<wr-checkbox(?![-\w])[^>]*?\s`;
|
|
27
|
+
const CHECKBOX_TAG = String.raw `<wr-checkbox(?![-\w])(?:"[^"]*"|'[^']*'|[^>])*?\s`;
|
|
20
28
|
const HTML_TRANSFORMS = [
|
|
21
29
|
// <wr-checkbox … value="x"> → checkboxValue="x"
|
|
22
30
|
{ pattern: new RegExp(`(${CHECKBOX_TAG})value=`, 'g'), replacement: '$1checkboxValue=' },
|
package/theme/styles/_focus.scss
CHANGED
|
@@ -83,11 +83,32 @@
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Command palette options
|
|
86
|
-
.wr-command-palette__option:focus-visible
|
|
87
|
-
.wr-command-palette__panel input:focus-visible {
|
|
86
|
+
.wr-command-palette__option:focus-visible {
|
|
88
87
|
@include focus-ring;
|
|
89
88
|
}
|
|
90
89
|
|
|
90
|
+
// The palette's search field gets NO ring, and this is the one place in the
|
|
91
|
+
// library that withholds one deliberately. The rule everywhere else — a
|
|
92
|
+
// component may inset the ring but must not cancel it — was written about
|
|
93
|
+
// `dropdown`, where focus ROVES between items and the ring is the only thing
|
|
94
|
+
// saying which one you are on. Nothing roves here.
|
|
95
|
+
//
|
|
96
|
+
// The palette autofocuses this field on open and focus never leaves it: the
|
|
97
|
+
// arrows move a highlight through `aria-activedescendant`, so the DOM's focused
|
|
98
|
+
// element is the input from the first frame to the last. An indicator that is
|
|
99
|
+
// on before the user has done anything, and that never moves afterwards,
|
|
100
|
+
// reports no state — it is a permanent blue box that reads as an error.
|
|
101
|
+
//
|
|
102
|
+
// What identifies focus here instead: the caret, which a text field draws on
|
|
103
|
+
// its own and which 2.4.7 accepts; the panel, which is modal and traps focus;
|
|
104
|
+
// and the placeholder plus the search icon, which say what the field is. Insetting
|
|
105
|
+
// was tried first and does not help — an outline on a full-bleed field traces
|
|
106
|
+
// the same rectangle two pixels in.
|
|
107
|
+
//
|
|
108
|
+
// If a future palette ever moves real focus between rows, that variant needs the
|
|
109
|
+
// ring back, and it should be scoped to the roving element rather than reinstated
|
|
110
|
+
// here.
|
|
111
|
+
|
|
91
112
|
// Mention option rows
|
|
92
113
|
.wr-mention-panel__option:focus-visible {
|
|
93
114
|
@include focus-ring;
|
|
@@ -69,8 +69,14 @@ declare class WrCommandPalette {
|
|
|
69
69
|
readonly placeholder: _angular_core.InputSignal<string | null>;
|
|
70
70
|
/** Text shown when no items match. Falls back to `commandPalette.noResults`. */
|
|
71
71
|
readonly emptyText: _angular_core.InputSignal<string | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Overrides the `commandPalette.loading` catalog string, shown instead of
|
|
74
|
+
* {@link emptyText} while {@link loading} is true.
|
|
75
|
+
*/
|
|
76
|
+
readonly loadingText: _angular_core.InputSignal<string | null>;
|
|
72
77
|
protected readonly resolvedPlaceholder: _angular_core.Signal<string>;
|
|
73
78
|
protected readonly resolvedEmpty: _angular_core.Signal<string>;
|
|
79
|
+
protected readonly resolvedLoading: _angular_core.Signal<string>;
|
|
74
80
|
/**
|
|
75
81
|
* The key-cap chip beside the search field. It was the literal `esc` in the
|
|
76
82
|
* template — the one string on this component no catalog could reach, so a
|
|
@@ -89,7 +95,47 @@ declare class WrCommandPalette {
|
|
|
89
95
|
readonly responsive: _angular_core.InputSignalWithTransform<boolean | undefined, BooleanInput>;
|
|
90
96
|
/** Fires when the user commits an item (Enter / click). */
|
|
91
97
|
readonly picked: _angular_core.OutputEmitterRef<WrCommandItem>;
|
|
92
|
-
|
|
98
|
+
/**
|
|
99
|
+
* The search text. Two-way, so a host can seed it, clear it, or read what the
|
|
100
|
+
* user is looking for — the palette used to keep this to itself, which is what
|
|
101
|
+
* made it impossible to back with anything but a static `items` array.
|
|
102
|
+
*
|
|
103
|
+
* Writing it does NOT re-run a host's search on its own: the debounced
|
|
104
|
+
* {@link searchChange} output is what fires, on exactly the cadence
|
|
105
|
+
* {@link debounceMs} sets.
|
|
106
|
+
*/
|
|
107
|
+
readonly query: _angular_core.ModelSignal<string>;
|
|
108
|
+
/**
|
|
109
|
+
* The item list is already scoped to the query upstream — skip the built-in
|
|
110
|
+
* client-side filter. Set it when `[items]` is fed from a server via the
|
|
111
|
+
* {@link searchChange} output.
|
|
112
|
+
*
|
|
113
|
+
* Without this, a backend that ranks or tolerates typos (returning rows whose
|
|
114
|
+
* labels do not literally contain the query) would have those rows hidden
|
|
115
|
+
* again on the client — the same rule `wr-select` follows, and the same
|
|
116
|
+
* reason. @default false
|
|
117
|
+
*/
|
|
118
|
+
readonly serverSearch: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
119
|
+
/**
|
|
120
|
+
* A host-driven search is in flight. Swaps the empty row for
|
|
121
|
+
* {@link loadingText} — an async palette that says "No results" between every
|
|
122
|
+
* keystroke and its answer is stating something false. @default false
|
|
123
|
+
*/
|
|
124
|
+
readonly loading: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
125
|
+
/**
|
|
126
|
+
* How long the query must settle before {@link searchChange} fires, in ms.
|
|
127
|
+
* A search request per keystroke is what exhausts a metered search backend:
|
|
128
|
+
* typing `select` is six requests at 0 and roughly one at 250. @default 250
|
|
129
|
+
*/
|
|
130
|
+
readonly debounceMs: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
131
|
+
/**
|
|
132
|
+
* The settled query. This is the hook for a server-backed palette: dispatch
|
|
133
|
+
* on it, then feed the result into `[items]` with `[serverSearch]` set.
|
|
134
|
+
*
|
|
135
|
+
* Fires on the {@link debounceMs} cadence, NOT per keystroke — `queryChange`
|
|
136
|
+
* is the per-keystroke signal if that is what you want.
|
|
137
|
+
*/
|
|
138
|
+
readonly searchChange: _angular_core.OutputEmitterRef<string>;
|
|
93
139
|
protected readonly activeIndex: _angular_core.WritableSignal<number>;
|
|
94
140
|
/** Whether the current opening is presented full-screen. Decided on open. */
|
|
95
141
|
protected readonly presentAsSheet: _angular_core.WritableSignal<boolean>;
|
|
@@ -124,6 +170,17 @@ declare class WrCommandPalette {
|
|
|
124
170
|
* and holds it, so that is retained DOM, not just a stray object.
|
|
125
171
|
*/
|
|
126
172
|
private destroyed;
|
|
173
|
+
/** Whether this palette filters `items` itself. */
|
|
174
|
+
protected readonly clientFilter: _angular_core.Signal<boolean>;
|
|
175
|
+
/**
|
|
176
|
+
* Nothing has been asked yet, so there is nothing to report as missing.
|
|
177
|
+
*
|
|
178
|
+
* A client-filtered palette cannot reach this state — an empty query matches
|
|
179
|
+
* every item, so the list is never empty on open. A server-backed one opens
|
|
180
|
+
* with no items by construction, and saying "No results" before a single
|
|
181
|
+
* keystroke answers a question nobody asked.
|
|
182
|
+
*/
|
|
183
|
+
protected readonly awaitingQuery: _angular_core.Signal<boolean>;
|
|
127
184
|
/** Grouped view — what the template renders. */
|
|
128
185
|
protected readonly buckets: _angular_core.Signal<readonly Bucket[]>;
|
|
129
186
|
/**
|
|
@@ -158,7 +215,7 @@ declare class WrCommandPalette {
|
|
|
158
215
|
private revealActive;
|
|
159
216
|
private commit;
|
|
160
217
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrCommandPalette, never>;
|
|
161
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrCommandPalette, "wr-command-palette", never, { "paletteLabel": { "alias": "paletteLabel"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "closeOnPick": { "alias": "closeOnPick"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; }, { "open": "openChange"; "picked": "picked"; }, never,
|
|
218
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrCommandPalette, "wr-command-palette", never, { "paletteLabel": { "alias": "paletteLabel"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "closeOnPick": { "alias": "closeOnPick"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "query": { "alias": "query"; "required": false; "isSignal": true; }; "serverSearch": { "alias": "serverSearch"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; }, { "open": "openChange"; "picked": "picked"; "query": "queryChange"; "searchChange": "searchChange"; }, never, ["[wrCommandPaletteFooter]"], true, never>;
|
|
162
219
|
}
|
|
163
220
|
|
|
164
221
|
export { WrCommandPalette };
|
package/types/ngwr-version.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { InjectionToken } from '@angular/core';
|
|
|
16
16
|
* Distinct from `Version` exported by `@angular/core`, which reports the
|
|
17
17
|
* loaded Angular runtime version (e.g. `'22.0.0'`), not ngwr's.
|
|
18
18
|
*/
|
|
19
|
-
declare const NGWR_VERSION = "14.0
|
|
19
|
+
declare const NGWR_VERSION = "14.2.0";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @license
|