@tocdk-oss/ng-spotlight 0.0.0-stage → 21.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thomas Christensen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,202 @@
1
- # Temporary Holding Version
1
+ # ng-spotlight
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![CI](https://github.com/tocDK/ng-spotlight/actions/workflows/ci.yml/badge.svg)](https://github.com/tocDK/ng-spotlight/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/@tocdk-oss/ng-spotlight.svg)](https://www.npmjs.com/package/@tocdk-oss/ng-spotlight)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+ [![Angular 21](https://img.shields.io/badge/angular-21-dd0031.svg)](https://angular.dev/)
7
+
8
+ **A keyboard-first spotlight / command palette for Angular.**
9
+ Press <kbd>Ctrl</kbd>+<kbd>Space</kbd> (or <kbd>⌘</kbd>/<kbd>Ctrl</kbd>+<kbd>K</kbd>), type, and jump straight to a page, a record or a command.
10
+
11
+ ## Why
12
+
13
+ Apps with many pages and lots of records are slow to navigate by menu. ng-spotlight gives every Angular app a fast "jump anywhere" box, like macOS Spotlight or Home Assistant's quick search:
14
+
15
+ - **Pages are added automatically** from your Angular routes. A new route is searchable the moment it merges, and a CI helper fails the build on routes without a label.
16
+ - **Your own data** comes from any backend through one HTTP endpoint (or a custom source), with results grouped for the UI: customers, orders, users and so on.
17
+ - **Default + override everywhere.** The response format, request shape, texts, recent-item storage, row design and theme all work out of the box, and any of them can be replaced globally or per source.
18
+ - **Headless core, design on top.** It ships with a CSS-variable default theme, or no CSS at all, and a **PrimeNG adapter** that picks up your PrimeNG theme. More adapters can plug into the same renderer contract.
19
+ - **Accessible.** WAI-ARIA combobox pattern, fully keyboard-driven, checked with axe.
20
+
21
+ ## Quick look
22
+
23
+ ```ts
24
+ // app.config.ts
25
+ import { provideSpotlight, routeSource, staticSource, httpSource } from '@tocdk-oss/ng-spotlight';
26
+
27
+ provideSpotlight({
28
+ hotkeys: ['ctrl.space', 'mod.k'],
29
+ sources: [
30
+ routeSource({ group: 'Pages' }),
31
+ staticSource({ group: 'Commands', items: [{ id: 'logout', title: 'Log out', action: { run: () => auth.logout() } }] }),
32
+ httpSource({ url: '/api/search' }),
33
+ ],
34
+ });
35
+ ```
36
+
37
+ ```html
38
+ <!-- once, in your app shell -->
39
+ <spotlight-host />
40
+ <button spotlightTrigger>Search</button>
41
+ ```
42
+
43
+ The HTTP source expects a simple grouped response by default, and you can map any other format:
44
+
45
+ ```json
46
+ { "groups": [{ "id": "customers", "label": "Customers", "total": 12,
47
+ "items": [{ "id": "263", "title": "Acme ApS", "subtitle": "CVR 12345678", "action": { "route": ["/customers", 263] } }] }] }
48
+ ```
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ npm i @tocdk-oss/ng-spotlight
54
+ ```
55
+
56
+ Peer dependencies: `@angular/core`, `@angular/common`, `@angular/router`, `@angular/cdk` and `rxjs`. Versions follow
57
+ Angular majors: `21.x` supports Angular 21. For the PrimeNG adapter you also need `primeng` 21 (optional peer).
58
+
59
+ ## Three-line setup
60
+
61
+ ```ts
62
+ // app.config.ts
63
+ import { provideRouter } from '@angular/router';
64
+ import { provideSpotlight, routeSource } from '@tocdk-oss/ng-spotlight';
65
+
66
+ export const appConfig = {
67
+ providers: [provideRouter(routes), provideSpotlight({ sources: [routeSource()] })],
68
+ };
69
+ ```
70
+
71
+ ```html
72
+ <!-- app shell, once -->
73
+ <spotlight-host />
74
+ <button spotlightTrigger>Search</button>
75
+ ```
76
+
77
+ Every route with a `title` (or `data.spotlight.label`, or `data.breadcrumb`) is now searchable. Routes with a `:param`
78
+ are skipped; `data: { spotlight: false }` opts a route out.
79
+
80
+ ## Sources
81
+
82
+ ```ts
83
+ import { localStorageRecent, provideSpotlight, routeSource, staticSource, httpSource } from '@tocdk-oss/ng-spotlight';
84
+
85
+ provideSpotlight({
86
+ hotkeys: ['ctrl.space', 'mod.k'], // default; 'mod' = Cmd on macOS, Ctrl elsewhere
87
+ texts: { placeholder: 'Search…' }, // string | Signal<string> | Observable<string>
88
+ recent: { max: 8, storage: localStorageRecent('app') }, // default storage: localStorage
89
+ theme: 'default', // or 'none'
90
+ onError: (err, source) => reportToSentry(err, source.id),
91
+ sources: [
92
+ routeSource({ group: 'Pages', filter: (route, url) => canSee(url) }),
93
+ staticSource({ group: 'Commands', items: [{ id: 'logout', title: 'Log out', action: { run: () => auth.logout() } }] }),
94
+ httpSource({ url: '/api/search' }), // needs provideHttpClient()
95
+ ],
96
+ });
97
+ ```
98
+
99
+ - `routeSource()` walks the Router config, including lazy children once loaded. Local results, ranked by the library.
100
+ - `staticSource({ group, items })` holds fixed commands. Local results.
101
+ - `httpSource({ url })` sends `GET {url}?q={query}` (plus `chip={groupId}` when a chip is active) and expects
102
+ `{ groups: [{ id, label, total?, items }] }` or a flat item array. Results keep the server's order. Override the
103
+ request and response globally (`provideSpotlight({ http: { request, map } })`) or per source
104
+ (`httpSource({ url, request, map })`). The JSON Schema ships as `@tocdk-oss/ng-spotlight/schema/spotlight-response.schema.json`.
105
+ - Any object implementing `SpotlightSource` is a source: `search(query, ctx)` may return items, a promise or an
106
+ Observable, and should stop when `ctx.signal` aborts.
107
+
108
+ Each item has an `action`: `{ route }` (Router), `{ url, newTab? }` (only http, https, mailto, tel and path-relative
109
+ URLs are allowed; protocol-relative `//host` URLs are blocked) or `{ run }`. The palette waits up to 5 seconds for a
110
+ `run()` promise, then closes anyway; `selected` fires when it settles. A query that starts with a source's `prefix` (for example `#` or `@`) searches only that source.
111
+ Call `provideSpotlight()` again in a lazy route's `providers` to add sources for that area. Such a child call only
112
+ adds `sources` (and `http` defaults for them); its `texts`, `hotkeys`, `recent`, `theme` and `onError` are ignored
113
+ (with a dev-mode warning) because the first call owns them. Pass `isolated: true` for a separate palette instead.
114
+ With several palettes on a page, one hotkey press reaches exactly one of them: the open one (so the hotkey closes it),
115
+ else the one opened most recently, else the `<spotlight-host>` created first. Place one `<spotlight-host>` per palette.
116
+
117
+ ## CI check for unlabelled routes
118
+
119
+ ```ts
120
+ import { spotlightRouteAudit } from '@tocdk-oss/ng-spotlight';
121
+
122
+ it('labels every admin route', () => {
123
+ expect(spotlightRouteAudit(adminRoutes)).toEqual([]);
124
+ });
125
+ ```
126
+
127
+ ## Templates
128
+
129
+ ```html
130
+ <spotlight-host>
131
+ <ng-template spotlightItem="customers" let-item>…</ng-template> <!-- per-group row -->
132
+ <ng-template spotlightItem let-item>…</ng-template> <!-- fallback row -->
133
+ <ng-template spotlightEmpty let-query>…</ng-template>
134
+ <ng-template spotlightFooter>…</ng-template>
135
+ </spotlight-host>
136
+ ```
137
+
138
+ ## Theming and PrimeNG
139
+
140
+ The default theme uses CSS variables only (`--sp-bg`, `--sp-fg`, `--sp-muted`, `--sp-accent`, `--sp-radius`,
141
+ `--sp-font`, `--sp-shadow`, …) and follows `prefers-color-scheme` (force a mode with the `sp-dark` / `sp-light` class).
142
+ `theme: 'none'` ships no CSS.
143
+
144
+ ```ts
145
+ import { provideSpotlightPrimeNG } from '@tocdk-oss/ng-spotlight/primeng';
146
+
147
+ providers: [providePrimeNG({ theme: { preset: Aura } }), provideSpotlight({ /* … */ }), provideSpotlightPrimeNG()];
148
+ ```
149
+
150
+ The adapter renders with `p-iconfield` + `pInputText`, `p-chip`, `p-tag` and `pi` icons and takes its colours from your
151
+ PrimeNG preset. Apps that never import `/primeng` never load PrimeNG. Other design systems: provide `SPOTLIGHT_RENDERER`
152
+ with your own part components (see "Build your own" in the docs).
153
+
154
+ ## Accessibility
155
+
156
+ WAI-ARIA combobox inside a modal dialog: `role="combobox"` input with `aria-activedescendant`, a `role="listbox"` of
157
+ labelled `role="group"`s and `role="option"`s, a focus trap with focus restore, and a polite live region for the result
158
+ count. Keys: ↑/↓ move, Enter opens, Ctrl/⌘+Enter opens links in a new tab, Tab/Shift+Tab switch chips, Esc closes.
159
+ The tests run axe on the open palette with zero violations. Note: macOS may use Ctrl+Space to switch input source,
160
+ which is why ⌘K is in the default set.
161
+
162
+ ## API
163
+
164
+ The whole public API, with every member, is snapshotted in [`api/ng-spotlight.api.md`](api/ng-spotlight.api.md) and
165
+ [`api/ng-spotlight-primeng.api.md`](api/ng-spotlight-primeng.api.md); CI fails when the built `.d.ts` drifts from them.
166
+
167
+ | Export | What it is |
168
+ |---|---|
169
+ | `provideSpotlight(config \| () => config)` | Sets up a palette (`SpotlightConfig`: `hotkeys`, `texts`, `recent`, `http`, `theme`, `onError`, `sources`, `isolated`) |
170
+ | `SpotlightService` | `open(query?)`, `close()`, `isOpen` (signal), `selected` (Observable of the chosen item). Nothing else is public |
171
+ | `<spotlight-host>`, `spotlightTrigger` | The palette, and a directive that opens it on click (`spotlightTrigger="#"` sets a query) |
172
+ | `spotlightItem`, `spotlightEmpty`, `spotlightFooter` | Templates, with `SpotlightItemTemplateContext` and `SpotlightEmptyTemplateContext` |
173
+ | `routeSource`, `staticSource`, `httpSource`, `spotlightRouteAudit` | Built-in sources and the route audit, with their `*Options` types |
174
+ | `SpotlightItem`, `SpotlightItemInput`, `SpotlightAction`, `SpotlightBadge`, `SpotlightSource`, `SpotlightContext`, `SpotlightResult`, `SpotlightResponse`, `SpotlightGroup`, `SpotlightHttpOptions`, `SpotlightHttpRequest`, `SpotlightRouteData` | Data types |
175
+ | `SpotlightTexts`, `SpotlightTextValue` | UI strings (keys left out keep their English defaults) |
176
+ | `localStorageRecent`, `SpotlightRecentStorage`, `SpotlightRecentEntry`, `SpotlightStoredAction` | Recent items and their storage |
177
+ | `SPOTLIGHT_RENDERER`, `SpotlightRenderer`, the part context types, `SpotlightDefault*` parts | Renderer contract for adapters |
178
+ | `/primeng`: `provideSpotlightPrimeNG()`, `SPOTLIGHT_PRIMENG_RENDERER`, `SpotlightPrimeNg*` parts | PrimeNG adapter |
179
+
180
+ ## Packages
181
+
182
+ | Import | What |
183
+ |---|---|
184
+ | `@tocdk-oss/ng-spotlight` | Headless core (Angular + CDK only) |
185
+ | `@tocdk-oss/ng-spotlight/primeng` | PrimeNG adapter (optional peer dependency) |
186
+
187
+ Versions follow Angular majors: `21.x` is for Angular 21.
188
+
189
+ ## Kitchen sink
190
+
191
+ A live demo with every feature, plus a **"Build your own"** guide (custom sources, translations via [`@tocdk/lingui-angular`](https://github.com/tocDK/lingui-angular), your own storage and adapter), is published at **https://tocdk.github.io/ng-spotlight/** by the Pages workflow. Every page shows its own source.
192
+
193
+ ## Docs
194
+
195
+ - [Changelog](CHANGELOG.md)
196
+ - [Contributing](CONTRIBUTING.md)
197
+ - [Design spec](docs/superpowers/specs/2026-11-02-ng-spotlight-design.md)
198
+ - [Implementation plan](docs/superpowers/plans/2026-11-02-ng-spotlight.md)
199
+
200
+ ## License
201
+
202
+ [MIT](LICENSE) © tocDK
@@ -0,0 +1,247 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, computed, makeEnvironmentProviders } from '@angular/core';
3
+ import { SPOTLIGHT_RENDERER } from '@tocdk-oss/ng-spotlight';
4
+ import { NgComponentOutlet } from '@angular/common';
5
+ import { Chip } from 'primeng/chip';
6
+ import { IconField } from 'primeng/iconfield';
7
+ import { InputIcon } from 'primeng/inputicon';
8
+ import { InputText } from 'primeng/inputtext';
9
+ import { Tag } from 'primeng/tag';
10
+
11
+ function toneToSeverity(tone) {
12
+ switch (tone) {
13
+ case 'info':
14
+ return 'info';
15
+ case 'success':
16
+ return 'success';
17
+ case 'warn':
18
+ return 'warn';
19
+ case 'danger':
20
+ return 'danger';
21
+ default:
22
+ return 'secondary';
23
+ }
24
+ }
25
+ /** Maps the core's --sp-* variables to PrimeNG design tokens, so presets and white-label themes apply. */
26
+ const SPOTLIGHT_PRIMENG_CSS = `
27
+ .sp-primeng {
28
+ --sp-bg: var(--p-content-background, #ffffff);
29
+ --sp-fg: var(--p-text-color, #334155);
30
+ --sp-muted: var(--p-text-muted-color, #64748b);
31
+ --sp-accent: var(--p-primary-color, #10b981);
32
+ --sp-accent-fg: var(--p-primary-contrast-color, #ffffff);
33
+ --sp-active-bg: var(--p-content-hover-background, #f1f5f9);
34
+ --sp-border: var(--p-content-border-color, #e2e8f0);
35
+ --sp-radius: var(--p-content-border-radius, 6px);
36
+ --sp-shadow: var(--p-overlay-modal-shadow, 0 20px 25px -5px rgba(0, 0, 0, 0.1));
37
+ --sp-font: inherit;
38
+ }
39
+ .sp-primeng-backdrop { --sp-backdrop: var(--p-mask-background, rgba(0, 0, 0, 0.4)); background: var(--sp-backdrop); }
40
+ .sp-primeng .sp-input { padding: 12px; }
41
+ .sp-primeng .sp-primeng-field { display: block; flex: 1; }
42
+ .sp-primeng .sp-primeng-field input { width: 100%; box-sizing: border-box; }
43
+ .sp-primeng .sp-chip-button .p-chip.sp-primeng-chip-active { background: var(--p-primary-color); color: var(--p-primary-contrast-color); }
44
+ `;
45
+ class SpotlightPrimeNgInput {
46
+ ctx = input.required(...(ngDevMode ? [{ debugName: "ctx" }] : /* istanbul ignore next */ []));
47
+ /** @internal */
48
+ onInput(event) {
49
+ this.ctx().onInput(event.target.value);
50
+ }
51
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
52
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.25", type: SpotlightPrimeNgInput, isStandalone: true, selector: "spotlight-primeng-input", inputs: { ctx: { classPropertyName: "ctx", publicName: "ctx", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
53
+ <p-iconfield class="sp-primeng-field">
54
+ <p-inputicon><i class="pi pi-search" aria-hidden="true"></i></p-inputicon>
55
+ <input
56
+ pInputText
57
+ type="text"
58
+ role="combobox"
59
+ autocomplete="off"
60
+ spellcheck="false"
61
+ aria-autocomplete="list"
62
+ [id]="ctx().id"
63
+ [value]="ctx().value"
64
+ [attr.placeholder]="ctx().placeholder"
65
+ [attr.aria-label]="ctx().label"
66
+ [attr.aria-expanded]="ctx().expanded"
67
+ [attr.aria-controls]="ctx().controls"
68
+ [attr.aria-activedescendant]="ctx().activeDescendant"
69
+ (input)="onInput($event)"
70
+ (keydown)="ctx().onKeydown($event)"
71
+ />
72
+ </p-iconfield>
73
+ `, isInline: true, styles: [".sp-primeng{--sp-bg: var(--p-content-background, #ffffff);--sp-fg: var(--p-text-color, #334155);--sp-muted: var(--p-text-muted-color, #64748b);--sp-accent: var(--p-primary-color, #10b981);--sp-accent-fg: var(--p-primary-contrast-color, #ffffff);--sp-active-bg: var(--p-content-hover-background, #f1f5f9);--sp-border: var(--p-content-border-color, #e2e8f0);--sp-radius: var(--p-content-border-radius, 6px);--sp-shadow: var(--p-overlay-modal-shadow, 0 20px 25px -5px rgba(0, 0, 0, .1));--sp-font: inherit}.sp-primeng-backdrop{--sp-backdrop: var(--p-mask-background, rgba(0, 0, 0, .4));background:var(--sp-backdrop)}.sp-primeng .sp-input{padding:12px}.sp-primeng .sp-primeng-field{display:block;flex:1}.sp-primeng .sp-primeng-field input{width:100%;box-sizing:border-box}.sp-primeng .sp-chip-button .p-chip.sp-primeng-chip-active{background:var(--p-primary-color);color:var(--p-primary-contrast-color)}\n"], dependencies: [{ kind: "component", type: IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "directive", type: InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
74
+ }
75
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgInput, decorators: [{
76
+ type: Component,
77
+ args: [{ selector: 'spotlight-primeng-input', imports: [IconField, InputIcon, InputText], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: `
78
+ <p-iconfield class="sp-primeng-field">
79
+ <p-inputicon><i class="pi pi-search" aria-hidden="true"></i></p-inputicon>
80
+ <input
81
+ pInputText
82
+ type="text"
83
+ role="combobox"
84
+ autocomplete="off"
85
+ spellcheck="false"
86
+ aria-autocomplete="list"
87
+ [id]="ctx().id"
88
+ [value]="ctx().value"
89
+ [attr.placeholder]="ctx().placeholder"
90
+ [attr.aria-label]="ctx().label"
91
+ [attr.aria-expanded]="ctx().expanded"
92
+ [attr.aria-controls]="ctx().controls"
93
+ [attr.aria-activedescendant]="ctx().activeDescendant"
94
+ (input)="onInput($event)"
95
+ (keydown)="ctx().onKeydown($event)"
96
+ />
97
+ </p-iconfield>
98
+ `, styles: [".sp-primeng{--sp-bg: var(--p-content-background, #ffffff);--sp-fg: var(--p-text-color, #334155);--sp-muted: var(--p-text-muted-color, #64748b);--sp-accent: var(--p-primary-color, #10b981);--sp-accent-fg: var(--p-primary-contrast-color, #ffffff);--sp-active-bg: var(--p-content-hover-background, #f1f5f9);--sp-border: var(--p-content-border-color, #e2e8f0);--sp-radius: var(--p-content-border-radius, 6px);--sp-shadow: var(--p-overlay-modal-shadow, 0 20px 25px -5px rgba(0, 0, 0, .1));--sp-font: inherit}.sp-primeng-backdrop{--sp-backdrop: var(--p-mask-background, rgba(0, 0, 0, .4));background:var(--sp-backdrop)}.sp-primeng .sp-input{padding:12px}.sp-primeng .sp-primeng-field{display:block;flex:1}.sp-primeng .sp-primeng-field input{width:100%;box-sizing:border-box}.sp-primeng .sp-chip-button .p-chip.sp-primeng-chip-active{background:var(--p-primary-color);color:var(--p-primary-contrast-color)}\n"] }]
99
+ }], propDecorators: { ctx: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctx", required: true }] }] } });
100
+ class SpotlightPrimeNgChip {
101
+ ctx = input.required(...(ngDevMode ? [{ debugName: "ctx" }] : /* istanbul ignore next */ []));
102
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
103
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.25", type: SpotlightPrimeNgChip, isStandalone: true, selector: "spotlight-primeng-chip", inputs: { ctx: { classPropertyName: "ctx", publicName: "ctx", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `<span aria-hidden="true"><p-chip [label]="ctx().label" [styleClass]="ctx().active ? 'sp-primeng-chip-active' : ''" /></span>`, isInline: true, dependencies: [{ kind: "component", type: Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
104
+ }
105
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgChip, decorators: [{
106
+ type: Component,
107
+ args: [{
108
+ selector: 'spotlight-primeng-chip',
109
+ imports: [Chip],
110
+ changeDetection: ChangeDetectionStrategy.OnPush,
111
+ template: `<span aria-hidden="true"><p-chip [label]="ctx().label" [styleClass]="ctx().active ? 'sp-primeng-chip-active' : ''" /></span>`,
112
+ }]
113
+ }], propDecorators: { ctx: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctx", required: true }] }] } });
114
+ class SpotlightPrimeNgGroupHeader {
115
+ ctx = input.required(...(ngDevMode ? [{ debugName: "ctx" }] : /* istanbul ignore next */ []));
116
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgGroupHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
117
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: SpotlightPrimeNgGroupHeader, isStandalone: true, selector: "spotlight-primeng-group-header", inputs: { ctx: { classPropertyName: "ctx", publicName: "ctx", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
118
+ <span class="sp-group-label">{{ ctx().label }}</span>
119
+ @if (ctx().total !== undefined) {
120
+ <!-- The separator keeps the group's accessible name readable: "Customers, 2". -->
121
+ <span style="position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0">, </span>
122
+ <span class="sp-group-total">{{ ctx().total }}</span>
123
+ }
124
+ @if (ctx().loading) {
125
+ <i class="pi pi-spin pi-spinner" aria-hidden="true"></i>
126
+ @if (ctx().loadingText) {
127
+ <span
128
+ style="position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0"
129
+ >, {{ ctx().loadingText }}</span
130
+ >
131
+ }
132
+ }
133
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
134
+ }
135
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgGroupHeader, decorators: [{
136
+ type: Component,
137
+ args: [{
138
+ selector: 'spotlight-primeng-group-header',
139
+ changeDetection: ChangeDetectionStrategy.OnPush,
140
+ template: `
141
+ <span class="sp-group-label">{{ ctx().label }}</span>
142
+ @if (ctx().total !== undefined) {
143
+ <!-- The separator keeps the group's accessible name readable: "Customers, 2". -->
144
+ <span style="position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0">, </span>
145
+ <span class="sp-group-total">{{ ctx().total }}</span>
146
+ }
147
+ @if (ctx().loading) {
148
+ <i class="pi pi-spin pi-spinner" aria-hidden="true"></i>
149
+ @if (ctx().loadingText) {
150
+ <span
151
+ style="position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0"
152
+ >, {{ ctx().loadingText }}</span
153
+ >
154
+ }
155
+ }
156
+ `,
157
+ }]
158
+ }], propDecorators: { ctx: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctx", required: true }] }] } });
159
+ class SpotlightPrimeNgBadge {
160
+ ctx = input.required(...(ngDevMode ? [{ debugName: "ctx" }] : /* istanbul ignore next */ []));
161
+ /** @internal */
162
+ severity = computed(() => toneToSeverity(this.ctx().badge.tone), ...(ngDevMode ? [{ debugName: "severity" }] : /* istanbul ignore next */ []));
163
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
164
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.25", type: SpotlightPrimeNgBadge, isStandalone: true, selector: "spotlight-primeng-badge", inputs: { ctx: { classPropertyName: "ctx", publicName: "ctx", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `<p-tag [value]="ctx().badge.label" [severity]="severity()" />`, isInline: true, dependencies: [{ kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
165
+ }
166
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgBadge, decorators: [{
167
+ type: Component,
168
+ args: [{
169
+ selector: 'spotlight-primeng-badge',
170
+ imports: [Tag],
171
+ changeDetection: ChangeDetectionStrategy.OnPush,
172
+ template: `<p-tag [value]="ctx().badge.label" [severity]="severity()" />`,
173
+ }]
174
+ }], propDecorators: { ctx: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctx", required: true }] }] } });
175
+ class SpotlightPrimeNgRow {
176
+ ctx = input.required(...(ngDevMode ? [{ debugName: "ctx" }] : /* istanbul ignore next */ []));
177
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgRow, deps: [], target: i0.ɵɵFactoryTarget.Component });
178
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: SpotlightPrimeNgRow, isStandalone: true, selector: "spotlight-primeng-row", inputs: { ctx: { classPropertyName: "ctx", publicName: "ctx", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
179
+ @let item = ctx().item;
180
+ @if (item.icon) {
181
+ <span class="sp-icon" aria-hidden="true"><i [class]="item.icon"></i></span>
182
+ }
183
+ <span class="sp-text">
184
+ <span class="sp-title">{{ item.title }}</span>
185
+ @if (item.subtitle) {
186
+ <span class="sp-subtitle">{{ item.subtitle }}</span>
187
+ }
188
+ </span>
189
+ @if (item.badges?.length) {
190
+ <span class="sp-badges">
191
+ @for (badge of item.badges ?? []; track $index) {
192
+ <ng-container *ngComponentOutlet="ctx().badge; inputs: { ctx: { badge: badge } }" />
193
+ }
194
+ </span>
195
+ }
196
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
197
+ }
198
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: SpotlightPrimeNgRow, decorators: [{
199
+ type: Component,
200
+ args: [{
201
+ selector: 'spotlight-primeng-row',
202
+ imports: [NgComponentOutlet],
203
+ changeDetection: ChangeDetectionStrategy.OnPush,
204
+ template: `
205
+ @let item = ctx().item;
206
+ @if (item.icon) {
207
+ <span class="sp-icon" aria-hidden="true"><i [class]="item.icon"></i></span>
208
+ }
209
+ <span class="sp-text">
210
+ <span class="sp-title">{{ item.title }}</span>
211
+ @if (item.subtitle) {
212
+ <span class="sp-subtitle">{{ item.subtitle }}</span>
213
+ }
214
+ </span>
215
+ @if (item.badges?.length) {
216
+ <span class="sp-badges">
217
+ @for (badge of item.badges ?? []; track $index) {
218
+ <ng-container *ngComponentOutlet="ctx().badge; inputs: { ctx: { badge: badge } }" />
219
+ }
220
+ </span>
221
+ }
222
+ `,
223
+ }]
224
+ }], propDecorators: { ctx: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctx", required: true }] }] } });
225
+
226
+ const SPOTLIGHT_PRIMENG_RENDERER = {
227
+ dialog: { panelClass: 'sp-primeng', backdropClass: 'sp-primeng-backdrop' },
228
+ input: SpotlightPrimeNgInput,
229
+ chips: SpotlightPrimeNgChip,
230
+ groupHeader: SpotlightPrimeNgGroupHeader,
231
+ row: SpotlightPrimeNgRow,
232
+ badge: SpotlightPrimeNgBadge,
233
+ };
234
+ /** Renders the palette with PrimeNG components. Use next to provideSpotlight() and providePrimeNG(). */
235
+ function provideSpotlightPrimeNG() {
236
+ return makeEnvironmentProviders([{ provide: SPOTLIGHT_RENDERER, useValue: SPOTLIGHT_PRIMENG_RENDERER }]);
237
+ }
238
+
239
+ // Public API for @tocdk-oss/ng-spotlight/primeng. Every change here must show up in
240
+ // api/ng-spotlight-primeng.api.md (npm run check:api).
241
+
242
+ /**
243
+ * Generated bundle index. Do not edit.
244
+ */
245
+
246
+ export { SPOTLIGHT_PRIMENG_RENDERER, SpotlightPrimeNgBadge, SpotlightPrimeNgChip, SpotlightPrimeNgGroupHeader, SpotlightPrimeNgInput, SpotlightPrimeNgRow, provideSpotlightPrimeNG };
247
+ //# sourceMappingURL=tocdk-oss-ng-spotlight-primeng.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tocdk-oss-ng-spotlight-primeng.mjs","sources":["../../../projects/ng-spotlight/primeng/src/primeng-parts.ts","../../../projects/ng-spotlight/primeng/src/provide-spotlight-primeng.ts","../../../projects/ng-spotlight/primeng/src/public-api.ts","../../../projects/ng-spotlight/primeng/src/tocdk-oss-ng-spotlight-primeng.ts"],"sourcesContent":["import { NgComponentOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport type {\n SpotlightBadgeContext,\n SpotlightBadgeTone,\n SpotlightChipContext,\n SpotlightGroupHeaderContext,\n SpotlightInputContext,\n SpotlightRowContext,\n} from '@tocdk-oss/ng-spotlight';\nimport { Chip } from 'primeng/chip';\nimport { IconField } from 'primeng/iconfield';\nimport { InputIcon } from 'primeng/inputicon';\nimport { InputText } from 'primeng/inputtext';\nimport { Tag } from 'primeng/tag';\n\nexport type SpotlightPrimeTagSeverity = 'success' | 'secondary' | 'info' | 'warn' | 'danger' | 'contrast';\n\nexport function toneToSeverity(tone: SpotlightBadgeTone | undefined): SpotlightPrimeTagSeverity {\n switch (tone) {\n case 'info':\n return 'info';\n case 'success':\n return 'success';\n case 'warn':\n return 'warn';\n case 'danger':\n return 'danger';\n default:\n return 'secondary';\n }\n}\n\n/** Maps the core's --sp-* variables to PrimeNG design tokens, so presets and white-label themes apply. */\nexport const SPOTLIGHT_PRIMENG_CSS = `\n.sp-primeng {\n --sp-bg: var(--p-content-background, #ffffff);\n --sp-fg: var(--p-text-color, #334155);\n --sp-muted: var(--p-text-muted-color, #64748b);\n --sp-accent: var(--p-primary-color, #10b981);\n --sp-accent-fg: var(--p-primary-contrast-color, #ffffff);\n --sp-active-bg: var(--p-content-hover-background, #f1f5f9);\n --sp-border: var(--p-content-border-color, #e2e8f0);\n --sp-radius: var(--p-content-border-radius, 6px);\n --sp-shadow: var(--p-overlay-modal-shadow, 0 20px 25px -5px rgba(0, 0, 0, 0.1));\n --sp-font: inherit;\n}\n.sp-primeng-backdrop { --sp-backdrop: var(--p-mask-background, rgba(0, 0, 0, 0.4)); background: var(--sp-backdrop); }\n.sp-primeng .sp-input { padding: 12px; }\n.sp-primeng .sp-primeng-field { display: block; flex: 1; }\n.sp-primeng .sp-primeng-field input { width: 100%; box-sizing: border-box; }\n.sp-primeng .sp-chip-button .p-chip.sp-primeng-chip-active { background: var(--p-primary-color); color: var(--p-primary-contrast-color); }\n`;\n\n@Component({\n selector: 'spotlight-primeng-input',\n imports: [IconField, InputIcon, InputText],\n encapsulation: ViewEncapsulation.None,\n styles: [SPOTLIGHT_PRIMENG_CSS],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <p-iconfield class=\"sp-primeng-field\">\n <p-inputicon><i class=\"pi pi-search\" aria-hidden=\"true\"></i></p-inputicon>\n <input\n pInputText\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [id]=\"ctx().id\"\n [value]=\"ctx().value\"\n [attr.placeholder]=\"ctx().placeholder\"\n [attr.aria-label]=\"ctx().label\"\n [attr.aria-expanded]=\"ctx().expanded\"\n [attr.aria-controls]=\"ctx().controls\"\n [attr.aria-activedescendant]=\"ctx().activeDescendant\"\n (input)=\"onInput($event)\"\n (keydown)=\"ctx().onKeydown($event)\"\n />\n </p-iconfield>\n `,\n})\nexport class SpotlightPrimeNgInput {\n readonly ctx = input.required<SpotlightInputContext>();\n\n /** @internal */\n protected onInput(event: Event): void {\n this.ctx().onInput((event.target as HTMLInputElement).value);\n }\n}\n\n@Component({\n selector: 'spotlight-primeng-chip',\n imports: [Chip],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<span aria-hidden=\"true\"><p-chip [label]=\"ctx().label\" [styleClass]=\"ctx().active ? 'sp-primeng-chip-active' : ''\" /></span>`,\n})\nexport class SpotlightPrimeNgChip {\n readonly ctx = input.required<SpotlightChipContext>();\n}\n\n@Component({\n selector: 'spotlight-primeng-group-header',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <span class=\"sp-group-label\">{{ ctx().label }}</span>\n @if (ctx().total !== undefined) {\n <!-- The separator keeps the group's accessible name readable: \"Customers, 2\". -->\n <span style=\"position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0\">, </span>\n <span class=\"sp-group-total\">{{ ctx().total }}</span>\n }\n @if (ctx().loading) {\n <i class=\"pi pi-spin pi-spinner\" aria-hidden=\"true\"></i>\n @if (ctx().loadingText) {\n <span\n style=\"position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0\"\n >, {{ ctx().loadingText }}</span\n >\n }\n }\n `,\n})\nexport class SpotlightPrimeNgGroupHeader {\n readonly ctx = input.required<SpotlightGroupHeaderContext>();\n}\n\n@Component({\n selector: 'spotlight-primeng-badge',\n imports: [Tag],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<p-tag [value]=\"ctx().badge.label\" [severity]=\"severity()\" />`,\n})\nexport class SpotlightPrimeNgBadge {\n readonly ctx = input.required<SpotlightBadgeContext>();\n /** @internal */\n protected readonly severity = computed(() => toneToSeverity(this.ctx().badge.tone));\n}\n\n@Component({\n selector: 'spotlight-primeng-row',\n imports: [NgComponentOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @let item = ctx().item;\n @if (item.icon) {\n <span class=\"sp-icon\" aria-hidden=\"true\"><i [class]=\"item.icon\"></i></span>\n }\n <span class=\"sp-text\">\n <span class=\"sp-title\">{{ item.title }}</span>\n @if (item.subtitle) {\n <span class=\"sp-subtitle\">{{ item.subtitle }}</span>\n }\n </span>\n @if (item.badges?.length) {\n <span class=\"sp-badges\">\n @for (badge of item.badges ?? []; track $index) {\n <ng-container *ngComponentOutlet=\"ctx().badge; inputs: { ctx: { badge: badge } }\" />\n }\n </span>\n }\n `,\n})\nexport class SpotlightPrimeNgRow {\n readonly ctx = input.required<SpotlightRowContext>();\n}\n","import { makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\nimport { SPOTLIGHT_RENDERER, type SpotlightRenderer } from '@tocdk-oss/ng-spotlight';\nimport {\n SpotlightPrimeNgBadge,\n SpotlightPrimeNgChip,\n SpotlightPrimeNgGroupHeader,\n SpotlightPrimeNgInput,\n SpotlightPrimeNgRow,\n} from './primeng-parts';\n\nexport const SPOTLIGHT_PRIMENG_RENDERER: SpotlightRenderer = {\n dialog: { panelClass: 'sp-primeng', backdropClass: 'sp-primeng-backdrop' },\n input: SpotlightPrimeNgInput,\n chips: SpotlightPrimeNgChip,\n groupHeader: SpotlightPrimeNgGroupHeader,\n row: SpotlightPrimeNgRow,\n badge: SpotlightPrimeNgBadge,\n};\n\n/** Renders the palette with PrimeNG components. Use next to provideSpotlight() and providePrimeNG(). */\nexport function provideSpotlightPrimeNG(): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: SPOTLIGHT_RENDERER, useValue: SPOTLIGHT_PRIMENG_RENDERER }]);\n}\n","// Public API for @tocdk-oss/ng-spotlight/primeng. Every change here must show up in\n// api/ng-spotlight-primeng.api.md (npm run check:api).\n\nexport { provideSpotlightPrimeNG, SPOTLIGHT_PRIMENG_RENDERER } from './provide-spotlight-primeng';\nexport {\n SpotlightPrimeNgBadge,\n SpotlightPrimeNgChip,\n SpotlightPrimeNgGroupHeader,\n SpotlightPrimeNgInput,\n SpotlightPrimeNgRow,\n} from './primeng-parts';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}