@mintplayer/ng-spark 22.24.0 → 22.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +5 -3
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-contributions.mjs +721 -0
- package/fesm2022/mintplayer-ng-spark-contributions.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-grid.mjs +131 -4
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-history.mjs +1 -14
- package/fesm2022/mintplayer-ng-spark-history.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs +41 -2
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-moderation.mjs +4 -4
- package/fesm2022/mintplayer-ng-spark-moderation.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-panels.mjs +9 -1
- package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +39 -3
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +15 -6
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +924 -16
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +78 -20
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +60 -5
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs +28 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-shell.mjs +31 -13
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark.mjs +4 -1
- package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
- package/package.json +7 -2
- package/types/mintplayer-ng-spark-client-operations.d.ts +7 -1
- package/types/mintplayer-ng-spark-contributions.d.ts +231 -0
- package/types/mintplayer-ng-spark-grid.d.ts +35 -3
- package/types/mintplayer-ng-spark-history.d.ts +3 -10
- package/types/mintplayer-ng-spark-models.d.ts +60 -3
- package/types/mintplayer-ng-spark-panels.d.ts +36 -1
- package/types/mintplayer-ng-spark-pipes.d.ts +12 -1
- package/types/mintplayer-ng-spark-po-detail.d.ts +4 -1
- package/types/mintplayer-ng-spark-po-edit.d.ts +305 -1
- package/types/mintplayer-ng-spark-po-form.d.ts +64 -15
- package/types/mintplayer-ng-spark-query-list.d.ts +26 -1
- package/types/mintplayer-ng-spark-renderers.d.ts +44 -2
- package/types/mintplayer-ng-spark-shell.d.ts +24 -9
- package/types/mintplayer-ng-spark.d.ts +12 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark-shell.mjs","names":[],"sources":["../../shell/src/spark-program-units.component.ts","../../shell/src/spark-program-units.component.html","../../shell/src/spark-language-selector.component.ts","../../shell/src/spark-shell-slots.ts","../../shell/src/spark-shell.component.ts","../../shell/src/spark-shell.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, effect, inject, input, signal, untracked } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { RouterLink, RouterLinkActive } from '@angular/router';\nimport { BsAccordionComponent, BsAccordionTabComponent, BsAccordionTabHeaderDirective } from '@mintplayer/ng-bootstrap/accordion';\nimport { SPARK_AUTH_STATE } from '@mintplayer/ng-spark';\nimport { ProgramUnitGroup } from '@mintplayer/ng-spark/models';\nimport { SparkService } from '@mintplayer/ng-spark/services';\nimport { IconNamePipe, ResolveTranslationPipe, RouterLinkPipe } from '@mintplayer/ng-spark/pipes';\nimport { SparkIconComponent } from '@mintplayer/ng-spark/icon';\nimport { SparkSidebarTab } from './spark-shell-slots';\n\n/**\n * The server-driven navigation menu: an accordion of program-unit groups fetched from\n * `GET /spark/program-units`, which the server has already filtered to what the caller's rights\n * allow. Hosts write ZERO router links for navigation — every group, unit, icon, label and link\n * comes from `programUnits.json`; content around the menu belongs in `<spark-shell>`'s slots,\n * and a host tempted to hand-write a unit anchor should add a unit to `programUnits.json`\n * instead.\n *\n * Because the response is caller-scoped it must be re-fetched when the caller changes: the\n * component tracks the optional `SPARK_AUTH_STATE` signal (supplied by ng-spark-auth's\n * `provideSparkAuth()`, or by the app's own auth stack) and reloads on every change. Without a\n * provider it fetches once. `reloadToken` is the manual escape hatch (any changed value triggers\n * a reload), and `reload()` the imperative one.\n *\n * Usually rendered by `<spark-shell>`; exported standalone for hosts that own their own layout.\n */\n@Component({\n selector: 'spark-program-units',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgTemplateOutlet,\n RouterLink, RouterLinkActive,\n BsAccordionComponent, BsAccordionTabComponent, BsAccordionTabHeaderDirective,\n SparkIconComponent, ResolveTranslationPipe, IconNamePipe, RouterLinkPipe,\n ],\n templateUrl: './spark-program-units.component.html',\n styleUrl: './spark-program-units.component.scss',\n})\nexport class SparkProgramUnitsComponent {\n private readonly sparkService = inject(SparkService);\n private readonly authState = inject(SPARK_AUTH_STATE, { optional: true });\n\n /** Any changed value triggers a reload — for apps whose auth state isn't a provided signal. */\n readonly reloadToken = input<unknown>(null);\n\n /**\n * Extra tabs to render after the generated groups, normally forwarded by `<spark-shell>` from\n * its `*sparkShellTab` directives. They must be rendered by THIS template — see\n * `SparkShellTabDirective` for why a host-declared `<bs-accordion-tab>` cannot work.\n */\n readonly extraTabs = input<readonly SparkSidebarTab[]>([]);\n\n protected readonly groups = signal<ProgramUnitGroup[]>([]);\n\n constructor() {\n effect(() => {\n this.authState?.();\n this.reloadToken();\n untracked(() => this.reload());\n });\n }\n\n /** Re-fetches the menu. The response is already rights-filtered per caller. */\n async reload(): Promise<void> {\n const config = await this.sparkService.getProgramUnits();\n // Order is the server file's contract, but sort both levels here so the rendered menu never\n // depends on JSON array order — groups were sorted, units were not (#324 F5).\n const groups = [...config.programUnitGroups]\n .sort((a, b) => a.order - b.order)\n .map(g => ({ ...g, programUnits: [...g.programUnits].sort((a, b) => a.order - b.order) }));\n this.groups.set(groups);\n }\n}\n","<bs-accordion class=\"d-block\">\n @for (group of groups(); track group.id) {\n <bs-accordion-tab>\n <ng-container *bsAccordionTabHeader>\n <spark-icon [name]=\"group.icon | iconName:'bi-folder'\" />\n <span class=\"ms-2\">{{ group.name | resolveTranslation }}</span>\n </ng-container>\n @for (unit of group.programUnits; track unit.id) {\n @if (unit | routerLink; as link) {\n <a [routerLink]=\"link\"\n routerLinkActive=\"active\"\n class=\"d-block px-3 py-2 text-decoration-none nav-link\">\n <spark-icon [name]=\"unit.icon | iconName:'bi-file'\" />\n <span class=\"ms-2\">{{ unit.name | resolveTranslation }}</span>\n </a>\n } @else {\n <!-- A url unit is an external address: a plain anchor, never a router link. -->\n <a [href]=\"unit.url\" target=\"_blank\" rel=\"noopener\"\n class=\"d-block px-3 py-2 text-decoration-none nav-link\">\n <spark-icon [name]=\"unit.icon | iconName:'bi-box-arrow-up-right'\" />\n <span class=\"ms-2\">{{ unit.name | resolveTranslation }}</span>\n </a>\n }\n }\n </bs-accordion-tab>\n }\n <!-- Host-contributed tabs are rendered HERE, by this template, so that the accordion's content\n query registers them and they join the generated groups' single-open group. -->\n @for (tab of extraTabs(); track tab.content) {\n <bs-accordion-tab>\n <ng-container *bsAccordionTabHeader>\n @if (tab.headerTemplate; as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <spark-icon [name]=\"tab.icon | iconName:'bi-folder'\" />\n <span class=\"ms-2\">{{ tab.header }}</span>\n }\n </ng-container>\n <ng-container *ngTemplateOutlet=\"tab.content\" />\n </bs-accordion-tab>\n }\n</bs-accordion>\n","import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\nimport { KeyValuePipe } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { BsSelectComponent, BsSelectOption } from '@mintplayer/ng-bootstrap/select';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport { ResolveTranslationPipe } from '@mintplayer/ng-spark/pipes';\n\n/**\n * The culture switcher: a `bs-select` over `SparkLanguageService`'s languages, persisting the\n * choice. Renders nothing when the app declares one language (or none), so hosts can include it\n * unconditionally — `<spark-shell>`'s topbar does exactly that as its trailing default.\n */\n@Component({\n selector: 'spark-language-selector',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [KeyValuePipe, FormsModule, BsSelectComponent, BsSelectOption, ResolveTranslationPipe],\n template: `\n @if (lang.languages() | keyvalue; as langs) {\n @if (langs.length > 1) {\n <bs-select [ngModel]=\"lang.language()\" (ngModelChange)=\"lang.setLanguage($event)\">\n @for (l of langs; track l.key) {\n <option [ngValue]=\"l.key\">{{ l.value | resolveTranslation }}</option>\n }\n </bs-select>\n }\n }\n `,\n})\nexport class SparkLanguageSelectorComponent {\n protected readonly lang = inject(SparkLanguageService);\n}\n","import { Directive, inject, input, TemplateRef } from '@angular/core';\n\n/**\n * Region slots for `<spark-shell>`.\n *\n * Each directive marks a template that REPLACES one region of the shell chrome (or fills an\n * empty one). An omitted slot is not an empty slot: the shell renders its default — the toggler,\n * the language selector, the title heading — so a host that supplies nothing still gets a\n * complete working shell, and a host that supplies one slot leaves the rest alone.\n *\n * The menu itself is deliberately NOT a slot. Navigation is sourced entirely from\n * `programUnits.json` through the rights-filtered `/spark/program-units` endpoint and re-fetched\n * on sign-in/out; a host that finds itself writing unit anchors in a slot should be adding units\n * to `programUnits.json` instead. Slots exist for the content AROUND the menu: an auth bar, a\n * user chip, branding, a one-off extra link, an alert strip above the routed content.\n *\n * Naming follows the house convention (prefix, component, slot — see `*sparkQueryIcon` in\n * `@mintplayer/ng-spark/grid`): `sparkShell` + region. Every slot also exists as a `TemplateRef`\n * input on `SparkShellComponent` for hosts that cannot use content projection.\n *\n * ```html\n * <spark-shell title=\"My App\">\n * <spark-auth-bar *sparkShellTopbarEnd />\n * <div *sparkShellSidebarTop>\n * <a routerLink=\"/github-projects\" class=\"nav-link\">GitHub projects</a>\n * </div>\n * <router-outlet />\n * </spark-shell>\n * ```\n */\n\n/** Topbar, leading edge. Default: a `bs-navbar-toggler` mirroring the shell's open state. */\n@Directive({ selector: '[sparkShellTopbarStart]' })\nexport class SparkShellTopbarStartDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * Topbar, trailing edge. Default: the language selector (which hides itself when the app has\n * one language). This is where an auth bar goes — the shell cannot ship one itself, since\n * `@mintplayer/ng-spark` does not (and must not) depend on `@mintplayer/ng-spark-auth`.\n */\n@Directive({ selector: '[sparkShellTopbarEnd]' })\nexport class SparkShellTopbarEndDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * Topbar, trailing edge, **beside** the default chrome rather than instead of it — rendered before\n * the language selector, which stays.\n *\n * ## Why this is not just `*sparkShellTopbarEnd`\n *\n * That slot REPLACES the region, which is right for an auth bar (a host taking over the trailing\n * edge wholesale) and wrong for a page-level action button. A host that only wanted to add a\n * button had to re-render the language selector itself to keep it — which means importing it,\n * knowing it hides itself in a single-language app, and keeping that copy in step with the shell.\n * Every host that did this got it slightly differently.\n *\n * Pairs with `SparkQueryActionsService`: that service resolves a query's custom actions without the\n * grid, and this is where a page-level one goes.\n *\n * ```html\n * <button *sparkShellTopbarActions class=\"btn btn-primary\" (click)=\"publish()\">Publish</button>\n * ```\n *\n * Supplying both slots is allowed and does what it says: `topbarEnd` replaces the default chrome,\n * and these actions still render ahead of whatever it put there.\n */\n@Directive({ selector: '[sparkShellTopbarActions]' })\nexport class SparkShellTopbarActionsDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/** Sidebar, above everything. Default: `<h5>{{ title }}</h5>`. */\n@Directive({ selector: '[sparkShellSidebarHeader]' })\nexport class SparkShellSidebarHeaderDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/** Sidebar, between the header and the program-units menu. No default. */\n@Directive({ selector: '[sparkShellSidebarTop]' })\nexport class SparkShellSidebarTopDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * An extra accordion tab in the sidebar menu, rendered after the generated program-unit groups\n * and sharing their single-open behavior.\n *\n * A tab is contributed as DATA (header + body template), not as markup, and that is load-bearing:\n * `bs-accordion` discovers its tabs with an Angular content query, which matches by declaration\n * view, so a `<bs-accordion-tab>` written in a host's template and inserted into the library's\n * accordion is never registered — it would land at index -1, get no hoisted header and no slot.\n * Declaring a second `<bs-accordion>` instead is what puts the tab in its own exclusivity group:\n * `mp-accordion` enforces single-open per element, over children it owns and over\n * `<details name>`, whose grouping cannot cross a shadow root. So the tab element must be created\n * by the menu itself, from what this directive carries.\n *\n * ```html\n * <ng-container *sparkShellTab=\"'Component demos'; icon: 'palette'\">\n * <a routerLink=\"/query-slots\" routerLinkActive=\"active\" class=\"nav-link\">Query card slots</a>\n * </ng-container>\n * ```\n *\n * Navigation still belongs in `programUnits.json` — this is for pages the model cannot describe\n * (client-side demos, external tools). For sidebar content that is NOT an accordion tab, use\n * `*sparkShellSidebarTop` or `*sparkShellSidebarFooter`.\n */\n@Directive({ selector: '[sparkShellTab]' })\nexport class SparkShellTabDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n\n /** The tab's header label. */\n readonly header = input.required<string>({ alias: 'sparkShellTab' });\n\n /** Bootstrap icon name for the header, as in `programUnits.json`. Defaults to a folder. */\n readonly icon = input<string | undefined>(undefined, { alias: 'sparkShellTabIcon' });\n\n /** Replaces the icon+label header entirely, for a header that needs its own markup. */\n readonly headerTemplate = input<TemplateRef<unknown> | null>(null, { alias: 'sparkShellTabHeader' });\n}\n\n/**\n * A sidebar accordion tab in the shape the menu renders it. Hosts normally contribute tabs with\n * `*sparkShellTab`; this is the same thing as data, for a host that computes its tabs.\n */\nexport interface SparkSidebarTab {\n readonly header: string;\n readonly icon?: string;\n readonly headerTemplate?: TemplateRef<unknown> | null;\n readonly content: TemplateRef<unknown>;\n}\n\n/** Sidebar, at the very bottom. No default. */\n@Directive({ selector: '[sparkShellSidebarFooter]' })\nexport class SparkShellSidebarFooterDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/** Main region, above the projected content (the host's `<router-outlet>`). No default. */\n@Directive({ selector: '[sparkShellMainHeader]' })\nexport class SparkShellMainHeaderDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n","import { ChangeDetectionStrategy, Component, computed, contentChild, contentChildren, input, signal, TemplateRef } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { BsShellComponent, BsShellSidebarDirective, BsShellState } from '@mintplayer/ng-bootstrap/shell';\nimport { BsNavbarTogglerComponent } from '@mintplayer/ng-bootstrap/navbar-toggler';\nimport type { Breakpoint } from '@mintplayer/ng-bootstrap';\nimport type { ShellStateChangeEventDetail } from '@mintplayer/web-components/shell';\nimport { SparkProgramUnitsComponent } from './spark-program-units.component';\nimport { SparkLanguageSelectorComponent } from './spark-language-selector.component';\nimport {\n SparkShellMainHeaderDirective,\n SparkShellSidebarFooterDirective,\n SparkShellSidebarHeaderDirective,\n SparkShellSidebarTopDirective,\n SparkShellTabDirective,\n SparkShellTopbarEndDirective,\n SparkShellTopbarActionsDirective,\n SparkShellTopbarStartDirective,\n SparkSidebarTab,\n} from './spark-shell-slots';\n\n/**\n * The application frame: topbar + sidebar + main, wrapping ng-bootstrap's `bs-shell` (whose\n * `mp-shell` web component owns ALL responsive behavior — breakpoints, the overlay drawer,\n * dismiss-on-navigate — in CSS; nothing here re-derives a pixel width). The sidebar renders the\n * server-driven program-units menu; the host projects its `<router-outlet>` as the default\n * content and customizes the chrome through the `*sparkShell*` slots (see `spark-shell-slots.ts`\n * for the doctrine: an omitted slot renders its default, and the menu itself is never a slot).\n *\n * ```html\n * <spark-shell title=\"My App\">\n * <spark-auth-bar *sparkShellTopbarEnd />\n * <router-outlet />\n * </spark-shell>\n * ```\n *\n * The one piece of state the shell keeps is the toggler↔drawer mirror: the built-in hamburger is\n * hidden (`::part(hamburger)`) in favor of a `bs-navbar-toggler` in the topbar, so the shell\n * listens to `statechange` to keep the toggler's icon truthful in `auto` mode and only forces\n * `show`/`hide` on explicit toggles.\n *\n * Theming: the chrome colors are CSS custom properties with the classic dark-sidebar defaults —\n * `--spark-shell-topbar-bg`, `--spark-shell-sidebar-bg`, `--spark-shell-main-bg` — overridable on\n * the `<spark-shell>` element. `sidebarTheme` flips the sidebar's `data-bs-theme` (which is what\n * recolors the accordion internals across the shadow boundary) together with its default palette.\n */\n@Component({\n selector: 'spark-shell',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgTemplateOutlet,\n BsShellComponent, BsShellSidebarDirective, BsNavbarTogglerComponent,\n SparkProgramUnitsComponent, SparkLanguageSelectorComponent,\n ],\n templateUrl: './spark-shell.component.html',\n styleUrl: './spark-shell.component.scss',\n})\nexport class SparkShellComponent {\n /** The sidebar heading. Ignored when a `*sparkShellSidebarHeader` slot is supplied. */\n readonly title = input('');\n\n /** Forwarded to `bs-shell`: below it the sidebar is an overlay drawer. */\n readonly breakpoint = input<Breakpoint>('md');\n\n /**\n * `data-bs-theme` for the sidebar — what flips the accordion's shadow-DOM internals between\n * palettes — plus the matching default background. `null` sets no theme (inherit the page's).\n */\n readonly sidebarTheme = input<'dark' | 'light' | null>('dark');\n\n /** Forwarded to the menu: any changed value re-fetches the program units. */\n readonly reloadToken = input<unknown>(null);\n\n /** Extra sidebar tabs as data, for hosts that compute them; `*sparkShellTab` is the usual way. */\n readonly sidebarTabs = input<readonly SparkSidebarTab[]>([]);\n\n // One TemplateRef input per slot, for hosts that cannot use content projection\n // (the spark-query-card precedent). The projected directive wins when both are present.\n readonly topbarStartTemplate = input<TemplateRef<unknown> | null>(null);\n readonly topbarEndTemplate = input<TemplateRef<unknown> | null>(null);\n readonly topbarActionsTemplate = input<TemplateRef<unknown> | null>(null);\n readonly sidebarHeaderTemplate = input<TemplateRef<unknown> | null>(null);\n readonly sidebarTopTemplate = input<TemplateRef<unknown> | null>(null);\n readonly sidebarFooterTemplate = input<TemplateRef<unknown> | null>(null);\n readonly mainHeaderTemplate = input<TemplateRef<unknown> | null>(null);\n\n private readonly topbarStartSlot = contentChild(SparkShellTopbarStartDirective);\n private readonly topbarEndSlot = contentChild(SparkShellTopbarEndDirective);\n private readonly topbarActionsSlot = contentChild(SparkShellTopbarActionsDirective);\n private readonly sidebarHeaderSlot = contentChild(SparkShellSidebarHeaderDirective);\n private readonly sidebarTopSlot = contentChild(SparkShellSidebarTopDirective);\n private readonly sidebarFooterSlot = contentChild(SparkShellSidebarFooterDirective);\n private readonly mainHeaderSlot = contentChild(SparkShellMainHeaderDirective);\n\n protected readonly topbarStartTpl = computed(() => this.topbarStartSlot()?.templateRef ?? this.topbarStartTemplate());\n protected readonly topbarEndTpl = computed(() => this.topbarEndSlot()?.templateRef ?? this.topbarEndTemplate());\n protected readonly topbarActionsTpl = computed(() => this.topbarActionsSlot()?.templateRef ?? this.topbarActionsTemplate());\n protected readonly sidebarHeaderTpl = computed(() => this.sidebarHeaderSlot()?.templateRef ?? this.sidebarHeaderTemplate());\n protected readonly sidebarTopTpl = computed(() => this.sidebarTopSlot()?.templateRef ?? this.sidebarTopTemplate());\n protected readonly sidebarFooterTpl = computed(() => this.sidebarFooterSlot()?.templateRef ?? this.sidebarFooterTemplate());\n protected readonly mainHeaderTpl = computed(() => this.mainHeaderSlot()?.templateRef ?? this.mainHeaderTemplate());\n\n /**\n * Extra accordion tabs, forwarded to the menu so IT creates the `<bs-accordion-tab>` elements —\n * the only way they share the generated groups' single-open behavior (see\n * `SparkShellTabDirective`). Data-supplied tabs come first, then projected ones in declaration\n * order.\n */\n private readonly tabSlots = contentChildren(SparkShellTabDirective);\n\n protected readonly tabs = computed<readonly SparkSidebarTab[]>(() => [\n ...this.sidebarTabs(),\n ...this.tabSlots().map(slot => ({\n header: slot.header(),\n icon: slot.icon(),\n headerTemplate: slot.headerTemplate(),\n content: slot.templateRef,\n })),\n ]);\n\n protected readonly shellState = signal<BsShellState>('auto');\n protected readonly isSidebarVisible = signal(false);\n\n // Explicit toggles force show/hide; 'auto' responsive behavior is otherwise preserved by\n // never writing state on our own. The mirror below keeps the toggler icon truthful when the\n // shell opens/closes itself at the breakpoint.\n protected toggleSidebar(open: boolean): void {\n this.shellState.set(open ? 'show' : 'hide');\n }\n\n protected onShellToggle(detail: ShellStateChangeEventDetail): void {\n this.isSidebarVisible.set(detail.open);\n }\n}\n","<bs-shell [state]=\"shellState()\" [breakpoint]=\"breakpoint()\" [dismissOnNavigate]=\"true\"\n (statechange)=\"onShellToggle($event)\">\n <div slot=\"topbar\" class=\"spark-topbar w-100 d-flex align-items-center\">\n @if (topbarStartTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <bs-navbar-toggler [state]=\"isSidebarVisible()\" (stateChange)=\"toggleSidebar($event)\" />\n }\n <div class=\"ms-auto me-3 d-flex align-items-center gap-2\">\n <!-- Ahead of the trailing chrome, and OUTSIDE the @if below: these actions are additive, so\n they render whether the host replaced the trailing edge or left the default selector. -->\n @if (topbarActionsTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n @if (topbarEndTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <spark-language-selector />\n }\n </div>\n </div>\n\n <nav bsShellSidebar class=\"spark-sidebar p-2\"\n [class.spark-sidebar-dark]=\"sidebarTheme() === 'dark'\"\n [attr.data-bs-theme]=\"sidebarTheme()\">\n @if (sidebarHeaderTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <h5 class=\"p-3 border-bottom\">{{ title() }}</h5>\n }\n @if (sidebarTopTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n <spark-program-units [reloadToken]=\"reloadToken()\" [extraTabs]=\"tabs()\" />\n @if (sidebarFooterTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n </nav>\n\n <!-- The padding lives in the stylesheet as `--spark-main-padding`, not as a `p-4` utility, so the\n sticky action bar can read it and bleed back out to the scrollport edges. See _actionbar.scss. -->\n <main>\n @if (mainHeaderTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n <ng-content />\n </main>\n</bs-shell>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-shell.mjs","names":[],"sources":["../../shell/src/spark-program-units.component.ts","../../shell/src/spark-program-units.component.html","../../shell/src/spark-language-selector.component.ts","../../shell/src/spark-shell-slots.ts","../../shell/src/spark-shell.component.ts","../../shell/src/spark-shell.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, effect, inject, input, signal, untracked } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { RouterLink, RouterLinkActive } from '@angular/router';\nimport { BsAccordionComponent, BsAccordionTabComponent, BsAccordionTabHeaderDirective } from '@mintplayer/ng-bootstrap/accordion';\nimport { SPARK_AUTH_STATE } from '@mintplayer/ng-spark';\nimport { ProgramUnitGroup } from '@mintplayer/ng-spark/models';\nimport { SparkService } from '@mintplayer/ng-spark/services';\nimport { IconNamePipe, ResolveTranslationPipe, RouterLinkPipe } from '@mintplayer/ng-spark/pipes';\nimport { SparkIconComponent } from '@mintplayer/ng-spark/icon';\nimport { SparkSidebarTab } from './spark-shell-slots';\n\n/**\n * The server-driven navigation menu: an accordion of program-unit groups fetched from\n * `GET /spark/program-units`, which the server has already filtered to what the caller's rights\n * allow. Hosts write ZERO router links for navigation — every group, unit, icon, label and link\n * comes from `programUnits.json`; content around the menu belongs in `<spark-shell>`'s slots,\n * and a host tempted to hand-write a unit anchor should add a unit to `programUnits.json`\n * instead.\n *\n * Because the response is caller-scoped it must be re-fetched when the caller changes: the\n * component tracks the optional `SPARK_AUTH_STATE` signal (supplied by ng-spark-auth's\n * `provideSparkAuth()`, or by the app's own auth stack) and reloads on every change. Without a\n * provider it fetches once. `reloadToken` is the manual escape hatch (any changed value triggers\n * a reload), and `reload()` the imperative one.\n *\n * Usually rendered by `<spark-shell>`; exported standalone for hosts that own their own layout.\n */\n@Component({\n selector: 'spark-program-units',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgTemplateOutlet,\n RouterLink, RouterLinkActive,\n BsAccordionComponent, BsAccordionTabComponent, BsAccordionTabHeaderDirective,\n SparkIconComponent, ResolveTranslationPipe, IconNamePipe, RouterLinkPipe,\n ],\n templateUrl: './spark-program-units.component.html',\n styleUrl: './spark-program-units.component.scss',\n})\nexport class SparkProgramUnitsComponent {\n private readonly sparkService = inject(SparkService);\n private readonly authState = inject(SPARK_AUTH_STATE, { optional: true });\n\n /** Any changed value triggers a reload — for apps whose auth state isn't a provided signal. */\n readonly reloadToken = input<unknown>(null);\n\n /**\n * Extra tabs to render after the generated groups, normally forwarded by `<spark-shell>` from\n * its `*sparkShellTab` directives. They must be rendered by THIS template — see\n * `SparkShellTabDirective` for why a host-declared `<bs-accordion-tab>` cannot work.\n */\n readonly extraTabs = input<readonly SparkSidebarTab[]>([]);\n\n protected readonly groups = signal<ProgramUnitGroup[]>([]);\n\n constructor() {\n effect(() => {\n this.authState?.();\n this.reloadToken();\n untracked(() => this.reload());\n });\n }\n\n /** Re-fetches the menu. The response is already rights-filtered per caller. */\n async reload(): Promise<void> {\n const config = await this.sparkService.getProgramUnits();\n // Order is the server file's contract, but sort both levels here so the rendered menu never\n // depends on JSON array order — groups were sorted, units were not (#324 F5).\n const groups = [...config.programUnitGroups]\n .sort((a, b) => a.order - b.order)\n .map(g => ({ ...g, programUnits: [...g.programUnits].sort((a, b) => a.order - b.order) }));\n this.groups.set(groups);\n }\n}\n","<bs-accordion class=\"d-block\">\n @for (group of groups(); track group.id) {\n <bs-accordion-tab>\n <ng-container *bsAccordionTabHeader>\n <spark-icon [name]=\"group.icon | iconName:'bi-folder'\" />\n <span class=\"ms-2\">{{ group.name | resolveTranslation }}</span>\n </ng-container>\n @for (unit of group.programUnits; track unit.id) {\n @if (unit | routerLink; as link) {\n <a [routerLink]=\"link\"\n routerLinkActive=\"active\"\n class=\"d-block px-3 py-2 text-decoration-none nav-link\">\n <spark-icon [name]=\"unit.icon | iconName:'bi-file'\" />\n <span class=\"ms-2\">{{ unit.name | resolveTranslation }}</span>\n </a>\n } @else {\n <!-- A url unit is an external address: a plain anchor, never a router link. -->\n <a [href]=\"unit.url\" target=\"_blank\" rel=\"noopener\"\n class=\"d-block px-3 py-2 text-decoration-none nav-link\">\n <spark-icon [name]=\"unit.icon | iconName:'bi-box-arrow-up-right'\" />\n <span class=\"ms-2\">{{ unit.name | resolveTranslation }}</span>\n </a>\n }\n }\n </bs-accordion-tab>\n }\n <!-- Host-contributed tabs are rendered HERE, by this template, so that the accordion's content\n query registers them and they join the generated groups' single-open group. -->\n @for (tab of extraTabs(); track tab.content) {\n <bs-accordion-tab>\n <ng-container *bsAccordionTabHeader>\n @if (tab.headerTemplate; as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <spark-icon [name]=\"tab.icon | iconName:'bi-folder'\" />\n <span class=\"ms-2\">{{ tab.header }}</span>\n }\n </ng-container>\n <ng-container *ngTemplateOutlet=\"tab.content\" />\n </bs-accordion-tab>\n }\n</bs-accordion>\n","import { ChangeDetectionStrategy, Component, inject } from '@angular/core';\nimport { KeyValuePipe } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { BsSelectComponent, BsSelectOption } from '@mintplayer/ng-bootstrap/select';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport { ResolveTranslationPipe } from '@mintplayer/ng-spark/pipes';\n\n/**\n * The culture switcher: a `bs-select` over `SparkLanguageService`'s languages, persisting the\n * choice. Renders nothing when the app declares one language (or none), so hosts can include it\n * unconditionally — `<spark-shell>`'s topbar does exactly that as its trailing default.\n */\n@Component({\n selector: 'spark-language-selector',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [KeyValuePipe, FormsModule, BsSelectComponent, BsSelectOption, ResolveTranslationPipe],\n template: `\n @if (lang.languages() | keyvalue; as langs) {\n @if (langs.length > 1) {\n <bs-select [ngModel]=\"lang.language()\" (ngModelChange)=\"lang.setLanguage($event)\">\n @for (l of langs; track l.key) {\n <option [ngValue]=\"l.key\">{{ l.value | resolveTranslation }}</option>\n }\n </bs-select>\n }\n }\n `,\n})\nexport class SparkLanguageSelectorComponent {\n protected readonly lang = inject(SparkLanguageService);\n}\n","import { Directive, inject, input, TemplateRef } from '@angular/core';\n\n/**\n * Region slots for `<spark-shell>`.\n *\n * Each directive marks a template that REPLACES one region of the shell chrome (or fills an\n * empty one). An omitted slot is not an empty slot: the shell renders its default — the toggler,\n * the language selector, the title heading — so a host that supplies nothing still gets a\n * complete working shell, and a host that supplies one slot leaves the rest alone.\n *\n * The menu itself is deliberately NOT a slot. Navigation is sourced entirely from\n * `programUnits.json` through the rights-filtered `/spark/program-units` endpoint and re-fetched\n * on sign-in/out; a host that finds itself writing unit anchors in a slot should be adding units\n * to `programUnits.json` instead. Slots exist for the content AROUND the menu: an auth bar, a\n * user chip, branding, a one-off extra link, an alert strip above the routed content.\n *\n * Naming follows the house convention (prefix, component, slot — see `*sparkQueryIcon` in\n * `@mintplayer/ng-spark/grid`): `sparkShell` + region. Every slot also exists as a `TemplateRef`\n * input on `SparkShellComponent` for hosts that cannot use content projection.\n *\n * ```html\n * <spark-shell title=\"My App\">\n * <spark-auth-bar *sparkShellTopbarEnd />\n * <div *sparkShellSidebarTop>\n * <a routerLink=\"/github-projects\" class=\"nav-link\">GitHub projects</a>\n * </div>\n * <router-outlet />\n * </spark-shell>\n * ```\n */\n\n/** Topbar, leading edge. Default: a `bs-navbar-toggler` mirroring the shell's open state. */\n@Directive({ selector: '[sparkShellTopbarStart]' })\nexport class SparkShellTopbarStartDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * Topbar, trailing edge. Default: the language selector (which hides itself when the app has\n * one language). This is where an auth bar goes — the shell cannot ship one itself, since\n * `@mintplayer/ng-spark` does not (and must not) depend on `@mintplayer/ng-spark-auth`.\n */\n@Directive({ selector: '[sparkShellTopbarEnd]' })\nexport class SparkShellTopbarEndDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * Topbar, trailing edge, **beside** the default chrome rather than instead of it — rendered before\n * the language selector, which stays.\n *\n * ## Why this is not just `*sparkShellTopbarEnd`\n *\n * That slot REPLACES the region, which is right for an auth bar (a host taking over the trailing\n * edge wholesale) and wrong for a page-level action button. A host that only wanted to add a\n * button had to re-render the language selector itself to keep it — which means importing it,\n * knowing it hides itself in a single-language app, and keeping that copy in step with the shell.\n * Every host that did this got it slightly differently.\n *\n * Pairs with `SparkQueryActionsService`: that service resolves a query's custom actions without the\n * grid, and this is where a page-level one goes.\n *\n * ```html\n * <button *sparkShellTopbarActions class=\"btn btn-primary\" (click)=\"publish()\">Publish</button>\n * ```\n *\n * Supplying both slots is allowed and does what it says: `topbarEnd` replaces the default chrome,\n * and these actions still render ahead of whatever it put there.\n */\n@Directive({ selector: '[sparkShellTopbarActions]' })\nexport class SparkShellTopbarActionsDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/** Sidebar, above everything. Default: `<h5>{{ title }}</h5>`. */\n@Directive({ selector: '[sparkShellSidebarHeader]' })\nexport class SparkShellSidebarHeaderDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/** Sidebar, between the header and the program-units menu. No default. */\n@Directive({ selector: '[sparkShellSidebarTop]' })\nexport class SparkShellSidebarTopDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * An extra accordion tab in the sidebar menu, rendered after the generated program-unit groups\n * and sharing their single-open behavior.\n *\n * A tab is contributed as DATA (header + body template), not as markup, and that is load-bearing:\n * `bs-accordion` discovers its tabs with an Angular content query, which matches by declaration\n * view, so a `<bs-accordion-tab>` written in a host's template and inserted into the library's\n * accordion is never registered — it would land at index -1, get no hoisted header and no slot.\n * Declaring a second `<bs-accordion>` instead is what puts the tab in its own exclusivity group:\n * `mp-accordion` enforces single-open per element, over children it owns and over\n * `<details name>`, whose grouping cannot cross a shadow root. So the tab element must be created\n * by the menu itself, from what this directive carries.\n *\n * ```html\n * <ng-container *sparkShellTab=\"'Component demos'; icon: 'palette'\">\n * <a routerLink=\"/query-slots\" routerLinkActive=\"active\" class=\"nav-link\">Query card slots</a>\n * </ng-container>\n * ```\n *\n * Navigation still belongs in `programUnits.json` — this is for pages the model cannot describe\n * (client-side demos, external tools). For sidebar content that is NOT an accordion tab, use\n * `*sparkShellSidebarTop` or `*sparkShellSidebarFooter`.\n */\n@Directive({ selector: '[sparkShellTab]' })\nexport class SparkShellTabDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n\n /** The tab's header label. */\n readonly header = input.required<string>({ alias: 'sparkShellTab' });\n\n /** Bootstrap icon name for the header, as in `programUnits.json`. Defaults to a folder. */\n readonly icon = input<string | undefined>(undefined, { alias: 'sparkShellTabIcon' });\n\n /** Replaces the icon+label header entirely, for a header that needs its own markup. */\n readonly headerTemplate = input<TemplateRef<unknown> | null>(null, { alias: 'sparkShellTabHeader' });\n}\n\n/**\n * A sidebar accordion tab in the shape the menu renders it. Hosts normally contribute tabs with\n * `*sparkShellTab`; this is the same thing as data, for a host that computes its tabs.\n */\nexport interface SparkSidebarTab {\n readonly header: string;\n readonly icon?: string;\n readonly headerTemplate?: TemplateRef<unknown> | null;\n readonly content: TemplateRef<unknown>;\n}\n\n/** Sidebar, at the very bottom. No default. */\n@Directive({ selector: '[sparkShellSidebarFooter]' })\nexport class SparkShellSidebarFooterDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/** Main region, above the projected content (the host's `<router-outlet>`). No default. */\n@Directive({ selector: '[sparkShellMainHeader]' })\nexport class SparkShellMainHeaderDirective {\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n","import { ChangeDetectionStrategy, Component, computed, contentChild, contentChildren, inject, input, signal, TemplateRef } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { BsShellComponent, BsShellSidebarDirective, BsShellState } from '@mintplayer/ng-bootstrap/shell';\nimport { BsNavbarTogglerComponent } from '@mintplayer/ng-bootstrap/navbar-toggler';\nimport { BS_THEME_DEFAULT_MODES, BsThemeService, BsThemeToggleComponent, BsThemeToggleMode } from '@mintplayer/ng-bootstrap/theming';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport type { Breakpoint } from '@mintplayer/ng-bootstrap';\nimport type { ShellStateChangeEventDetail } from '@mintplayer/web-components/shell';\nimport { SparkProgramUnitsComponent } from './spark-program-units.component';\nimport { SparkLanguageSelectorComponent } from './spark-language-selector.component';\nimport {\n SparkShellMainHeaderDirective,\n SparkShellSidebarFooterDirective,\n SparkShellSidebarHeaderDirective,\n SparkShellSidebarTopDirective,\n SparkShellTabDirective,\n SparkShellTopbarEndDirective,\n SparkShellTopbarActionsDirective,\n SparkShellTopbarStartDirective,\n SparkSidebarTab,\n} from './spark-shell-slots';\n\n/**\n * The application frame: topbar + sidebar + main, wrapping ng-bootstrap's `bs-shell` (whose\n * `mp-shell` web component owns ALL responsive behavior — breakpoints, the overlay drawer,\n * dismiss-on-navigate — in CSS; nothing here re-derives a pixel width). The sidebar renders the\n * server-driven program-units menu; the host projects its `<router-outlet>` as the default\n * content and customizes the chrome through the `*sparkShell*` slots (see `spark-shell-slots.ts`\n * for the doctrine: an omitted slot renders its default, and the menu itself is never a slot).\n *\n * ```html\n * <spark-shell title=\"My App\">\n * <spark-auth-bar *sparkShellTopbarEnd />\n * <router-outlet />\n * </spark-shell>\n * ```\n *\n * The one piece of state the shell keeps is the toggler↔drawer mirror: the built-in hamburger is\n * hidden (`::part(hamburger)`) in favor of a `bs-navbar-toggler` in the topbar, so the shell\n * listens to `statechange` to keep the toggler's icon truthful in `auto` mode and only forces\n * `show`/`hide` on explicit toggles.\n *\n * Theming: the chrome colors are CSS custom properties —\n * `--spark-shell-{topbar,sidebar,main}-{bg,color}` — declared per colour scheme under\n * `[data-bs-theme=light]` / `[data-bs-theme=dark]` from Bootstrap tokens, so the whole shell follows\n * the page's theme. An app restyles it by overriding those tokens, globally per scheme or on the\n * `<spark-shell>` element.\n *\n * Colour mode: the shell injects `BsThemeService` itself, so 'auto' follows the OS live even when\n * the topbar toggle is hidden with `[themeToggle]=\"false\"` (an app may then place its own\n * `<bs-theme-toggle>` elsewhere). The first paint is themed by `bs-theme-preboot.js` in the app's\n * `index.html`, not by anything here.\n */\n@Component({\n selector: 'spark-shell',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgTemplateOutlet,\n BsShellComponent, BsShellSidebarDirective, BsNavbarTogglerComponent, BsThemeToggleComponent,\n SparkProgramUnitsComponent, SparkLanguageSelectorComponent,\n ],\n templateUrl: './spark-shell.component.html',\n styleUrl: './spark-shell.component.scss',\n})\nexport class SparkShellComponent {\n /** The sidebar heading. Ignored when a `*sparkShellSidebarHeader` slot is supplied. */\n readonly title = input('');\n\n /** Forwarded to `bs-shell`: below it the sidebar is an overlay drawer. */\n readonly breakpoint = input<Breakpoint>('md');\n\n /**\n * Render the Auto / Light / Dark `bs-theme-toggle` in the topbar. `false` hides it; the theme\n * service stays live either way.\n */\n readonly themeToggle = input(true);\n\n /**\n * Instantiated here, not only through the toggle (PRD D3): without it, `[themeToggle]=\"false\"`\n * would leave 'auto' with no live `prefers-color-scheme` listener in Angular's view.\n */\n protected readonly theme = inject(BsThemeService);\n private readonly lang = inject(SparkLanguageService);\n\n /** The toggle's cycle with Spark's translated labels (`theme.*` keys); icons stay ng-bootstrap's. */\n protected readonly themeModes = computed<readonly BsThemeToggleMode[]>(() =>\n BS_THEME_DEFAULT_MODES.map(m => {\n const name = m.mode.charAt(0).toUpperCase() + m.mode.slice(1);\n return { ...m, label: this.lang.t(`theme.switchTo${name}`), announcement: this.lang.t(`theme.${m.mode}`) };\n }));\n\n /** Forwarded to the menu: any changed value re-fetches the program units. */\n readonly reloadToken = input<unknown>(null);\n\n /** Extra sidebar tabs as data, for hosts that compute them; `*sparkShellTab` is the usual way. */\n readonly sidebarTabs = input<readonly SparkSidebarTab[]>([]);\n\n // One TemplateRef input per slot, for hosts that cannot use content projection\n // (the spark-query-card precedent). The projected directive wins when both are present.\n readonly topbarStartTemplate = input<TemplateRef<unknown> | null>(null);\n readonly topbarEndTemplate = input<TemplateRef<unknown> | null>(null);\n readonly topbarActionsTemplate = input<TemplateRef<unknown> | null>(null);\n readonly sidebarHeaderTemplate = input<TemplateRef<unknown> | null>(null);\n readonly sidebarTopTemplate = input<TemplateRef<unknown> | null>(null);\n readonly sidebarFooterTemplate = input<TemplateRef<unknown> | null>(null);\n readonly mainHeaderTemplate = input<TemplateRef<unknown> | null>(null);\n\n private readonly topbarStartSlot = contentChild(SparkShellTopbarStartDirective);\n private readonly topbarEndSlot = contentChild(SparkShellTopbarEndDirective);\n private readonly topbarActionsSlot = contentChild(SparkShellTopbarActionsDirective);\n private readonly sidebarHeaderSlot = contentChild(SparkShellSidebarHeaderDirective);\n private readonly sidebarTopSlot = contentChild(SparkShellSidebarTopDirective);\n private readonly sidebarFooterSlot = contentChild(SparkShellSidebarFooterDirective);\n private readonly mainHeaderSlot = contentChild(SparkShellMainHeaderDirective);\n\n protected readonly topbarStartTpl = computed(() => this.topbarStartSlot()?.templateRef ?? this.topbarStartTemplate());\n protected readonly topbarEndTpl = computed(() => this.topbarEndSlot()?.templateRef ?? this.topbarEndTemplate());\n protected readonly topbarActionsTpl = computed(() => this.topbarActionsSlot()?.templateRef ?? this.topbarActionsTemplate());\n protected readonly sidebarHeaderTpl = computed(() => this.sidebarHeaderSlot()?.templateRef ?? this.sidebarHeaderTemplate());\n protected readonly sidebarTopTpl = computed(() => this.sidebarTopSlot()?.templateRef ?? this.sidebarTopTemplate());\n protected readonly sidebarFooterTpl = computed(() => this.sidebarFooterSlot()?.templateRef ?? this.sidebarFooterTemplate());\n protected readonly mainHeaderTpl = computed(() => this.mainHeaderSlot()?.templateRef ?? this.mainHeaderTemplate());\n\n /**\n * Extra accordion tabs, forwarded to the menu so IT creates the `<bs-accordion-tab>` elements —\n * the only way they share the generated groups' single-open behavior (see\n * `SparkShellTabDirective`). Data-supplied tabs come first, then projected ones in declaration\n * order.\n */\n private readonly tabSlots = contentChildren(SparkShellTabDirective);\n\n protected readonly tabs = computed<readonly SparkSidebarTab[]>(() => [\n ...this.sidebarTabs(),\n ...this.tabSlots().map(slot => ({\n header: slot.header(),\n icon: slot.icon(),\n headerTemplate: slot.headerTemplate(),\n content: slot.templateRef,\n })),\n ]);\n\n protected readonly shellState = signal<BsShellState>('auto');\n protected readonly isSidebarVisible = signal(false);\n\n // Explicit toggles force show/hide; 'auto' responsive behavior is otherwise preserved by\n // never writing state on our own. The mirror below keeps the toggler icon truthful when the\n // shell opens/closes itself at the breakpoint.\n protected toggleSidebar(open: boolean): void {\n this.shellState.set(open ? 'show' : 'hide');\n }\n\n protected onShellToggle(detail: ShellStateChangeEventDetail): void {\n this.isSidebarVisible.set(detail.open);\n }\n}\n","<bs-shell [state]=\"shellState()\" [breakpoint]=\"breakpoint()\" [dismissOnNavigate]=\"true\"\n (statechange)=\"onShellToggle($event)\">\n <div slot=\"topbar\" class=\"spark-topbar w-100 d-flex align-items-center\">\n @if (topbarStartTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <bs-navbar-toggler [state]=\"isSidebarVisible()\" (stateChange)=\"toggleSidebar($event)\" />\n }\n <div class=\"ms-auto me-3 d-flex align-items-center gap-2\">\n <!-- Ahead of the trailing chrome, and OUTSIDE the @if below: these actions are additive, so\n they render whether the host replaced the trailing edge or left the default selector. -->\n @if (topbarActionsTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n <!-- Also outside the trailing @if: replacing the end slot (e.g. with spark-auth-bar) keeps it. -->\n @if (themeToggle()) {\n <bs-theme-toggle [modes]=\"themeModes()\" />\n }\n @if (topbarEndTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <spark-language-selector />\n }\n </div>\n </div>\n\n <nav bsShellSidebar class=\"spark-sidebar p-2\">\n @if (sidebarHeaderTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n } @else {\n <h5 class=\"p-3 border-bottom\">{{ title() }}</h5>\n }\n @if (sidebarTopTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n <spark-program-units [reloadToken]=\"reloadToken()\" [extraTabs]=\"tabs()\" />\n @if (sidebarFooterTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n </nav>\n\n <!-- The padding lives in the stylesheet as `--spark-main-padding`, not as a `p-4` utility, so the\n sticky action bar can read it and bleed back out to the scrollport edges. See _actionbar.scss. -->\n <main>\n @if (mainHeaderTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\" />\n }\n <ng-content />\n </main>\n</bs-shell>\n"],"mappings":";;;;;;;;;;;;;;;AAwCA,IAAa,6BAAb,MAAa,2BAA0B;CACpB,eAAe,OAAO,YAAY;CAClC,YAAY,OAAO,kBAAkB,EAAE,UAAU,KAAI,CAAE;CAG/D,cAAc,MAAe,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAOlC,YAAY,MAAkC,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAEvC,SAAS,OAA2B,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CAE1D,cAAA;EACE,aAAY;GACV,KAAK,YAAW;GAChB,KAAK,YAAW;GAChB,gBAAgB,KAAK,OAAM,CAAE;EAC/B,CAAC;CACH;CAGA,MAAM,SAAM;EAIV,MAAM,SAAS,CAAC,IAAG,MAHE,KAAK,aAAa,gBAAe,EAGnC,CAAO,iBAAiB,CAAC,CACzC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CACjC,KAAI,OAAM;GAAE,GAAG;GAAG,cAAc,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;EAAC,EAAG;EAC3F,KAAK,OAAO,IAAI,MAAM;CACxB;CAjCW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA0B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA1B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA0B,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UCxCvC;EA0CA,QAAA,CAAA,sZAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MDVI;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAU,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,gBAAA;IAAA,UAAA,CAAA,kBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAC5B;IAAoB,UAAA;IAAA,QAAA,CAAA,SAAA,oBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAuB,UAAA;IAAA,QAAA,CAAA,YAAA,UAAA;IAAA,SAAA,CAAA,gBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAA6B,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAC5E;IAAkB,UAAA;IAAA,QAAA,CAAA,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAsB,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAY,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAc,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAK/D,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA0B,YAAA,CAAA;EAbtC,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAqB,YACnB;GAAI,iBACC,wBAAwB;GAAM,SACtC;IACP;IACA;IAAY;IACZ;IAAsB;IAAyB;IAC/C;IAAoB;IAAwB;IAAc;GAC3D;GAAA,UAAA;GAAA,QAAA,CAAA,sZAAA;EAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;AEPH,IAAa,iCAAb,MAAa,+BAA8B;CACtB,OAAO,OAAO,oBAAoB;CAD1C,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA8B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA9B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA8B,cAAA;EAAA,UAAA;EAAA,UAAA;EAAA,UAZ/B;;;;;;;;;;;EAUT,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAXuB;GAAW;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA,CAAA,WAAA,OAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA,CAAA,WAAA,OAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,eAAA;IAAA,UAAA,CAAA,SAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAiB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAc,UAAA;IAAA,QAAA,CAAA,WAAA,OAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAA5D;IAAY,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAkD;IAAsB,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAanF,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA8B,YAAA,CAAA;EAjB1C,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,YAAY;GACZ,iBAAiB,wBAAwB;GACzC,SAAS;IAAC;IAAc;IAAa;IAAmB;IAAgB;GAAsB;GAC9F,UAAU;;;;;;;;;;;EAWX,CAAA;;;ACKD,IAAa,iCAAb,MAAa,+BAA8B;CAChC,cAAc,OAA6B,WAAW;CADpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA8B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA9B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA8B,cAAA;EAAA,UAAA;EAAA,UAAA;CAAA,CAAA;;AAA9B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA8B,YAAA,CAAA;EAD1C,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,0BAAyB,CAAE;;;AAWlD,IAAa,+BAAb,MAAa,6BAA4B;CAC9B,cAAc,OAA6B,WAAW;CADpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA4B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA5B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA4B,cAAA;EAAA,UAAA;EAAA,UAAA;CAAA,CAAA;;AAA5B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA4B,YAAA,CAAA;EADxC,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,wBAAuB,CAAE;;;AA4BhD,IAAa,mCAAb,MAAa,iCAAgC;CAClC,cAAc,OAA6B,WAAW;CADpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAgC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAhC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAgC,cAAA;EAAA,UAAA;EAAA,UAAA;CAAA,CAAA;;AAAhC,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAgC,YAAA,CAAA;EAD5C,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,4BAA2B,CAAE;;;AAOpD,IAAa,mCAAb,MAAa,iCAAgC;CAClC,cAAc,OAA6B,WAAW;CADpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAgC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAhC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAgC,cAAA;EAAA,UAAA;EAAA,UAAA;CAAA,CAAA;;AAAhC,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAgC,YAAA,CAAA;EAD5C,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,4BAA2B,CAAE;;;AAOpD,IAAa,gCAAb,MAAa,8BAA6B;CAC/B,cAAc,OAA6B,WAAW;CADpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA6B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA7B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA6B,cAAA;EAAA,UAAA;EAAA,UAAA;CAAA,CAAA;;AAA7B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA6B,YAAA,CAAA;EADzC,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,yBAAwB,CAAE;;;AA6BjD,IAAa,yBAAb,MAAa,uBAAsB;CACxB,cAAc,OAA6B,WAAW;CAGtD,SAAS,MAAM,SAAQ;EAAA,GAAA,YAAA,EAAA,WAAA,SAAA,+BAAA,CAAA;EAAW,OAAO;CAAe,CAAA;CAGxD,OAAO,MAA0B,QAAS;EAAA,GAAA,YAAA,EAAA,WAAA,OAAA,+BAAA,CAAA;EAAI,OAAO;CAAmB,CAAA;CAGxE,iBAAiB,MAAmC,MAAI;EAAA,GAAA,YAAA,EAAA,WAAA,iBAAA,+BAAA,CAAA;EAAI,OAAO;CAAqB,CAAA;CAVtF,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAsB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAtB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAsB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,gBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;CAAA,CAAA;;AAAtB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAsB,YAAA,CAAA;EADlC,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,kBAAiB,CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2B1C,IAAa,mCAAb,MAAa,iCAAgC;CAClC,cAAc,OAA6B,WAAW;CADpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAgC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAhC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAgC,cAAA;EAAA,UAAA;EAAA,UAAA;CAAA,CAAA;;AAAhC,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAgC,YAAA,CAAA;EAD5C,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,4BAA2B,CAAE;;;AAOpD,IAAa,gCAAb,MAAa,8BAA6B;CAC/B,cAAc,OAA6B,WAAW;CADpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA6B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA7B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA6B,cAAA;EAAA,UAAA;EAAA,UAAA;CAAA,CAAA;;AAA7B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA6B,YAAA,CAAA;EADzC,MAAA;EAAU,MAAA,CAAA,EAAE,UAAU,yBAAwB,CAAE;;;AC5EjD,IAAa,sBAAb,MAAa,oBAAmB;CAErB,QAAQ,MAAM,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAGjB,aAAa,MAAkB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAMpC,cAAc,MAAM,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAMf,QAAQ,OAAO,cAAc;CAC/B,OAAO,OAAO,oBAAoB;CAGhC,aAAa,eAC9B,uBAAuB,KAAI,MAAI;EAC7B,MAAM,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,YAAW,IAAK,EAAE,KAAK,MAAM,CAAC;EAC5D,OAAO;GAAE,GAAG;GAAG,OAAO,KAAK,KAAK,EAAE,iBAAiB,MAAM;GAAG,cAAc,KAAK,KAAK,EAAE,SAAS,EAAE,MAAM;EAAC;CAC1G,CAAC,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAGI,cAAc,MAAe,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAGlC,cAAc,MAAkC,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAInD,sBAAsB,MAAmC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,sBAAA,CAAA,+BAAA,CAAA,CAAA;CAC9D,oBAAoB,MAAmC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,oBAAA,CAAA,+BAAA,CAAA,CAAA;CAC5D,wBAAwB,MAAmC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,wBAAA,CAAA,+BAAA,CAAA,CAAA;CAChE,wBAAwB,MAAmC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,wBAAA,CAAA,+BAAA,CAAA,CAAA;CAChE,qBAAqB,MAAmC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,qBAAA,CAAA,+BAAA,CAAA,CAAA;CAC7D,wBAAwB,MAAmC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,wBAAA,CAAA,+BAAA,CAAA,CAAA;CAChE,qBAAqB,MAAmC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,qBAAA,CAAA,+BAAA,CAAA,CAAA;CAErD,kBAAkB,aAAa,gCAA+B,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;CAC9D,gBAAgB,aAAa,8BAA6B,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAC1D,oBAAoB,aAAa,kCAAiC,GAAA,YAAA,CAAA,EAAA,WAAA,oBAAA,CAAA,+BAAA,CAAA,CAAA;CAClE,oBAAoB,aAAa,kCAAiC,GAAA,YAAA,CAAA,EAAA,WAAA,oBAAA,CAAA,+BAAA,CAAA,CAAA;CAClE,iBAAiB,aAAa,+BAA8B,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAC5D,oBAAoB,aAAa,kCAAiC,GAAA,YAAA,CAAA,EAAA,WAAA,oBAAA,CAAA,+BAAA,CAAA,CAAA;CAClE,iBAAiB,aAAa,+BAA8B,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAE1D,iBAAiB,eAAe,KAAK,gBAAe,CAAE,EAAE,eAAe,KAAK,oBAAmB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAClG,eAAe,eAAe,KAAK,cAAa,CAAE,EAAE,eAAe,KAAK,kBAAiB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAC5F,mBAAmB,eAAe,KAAK,kBAAiB,CAAE,EAAE,eAAe,KAAK,sBAAqB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CACxG,mBAAmB,eAAe,KAAK,kBAAiB,CAAE,EAAE,eAAe,KAAK,sBAAqB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CACxG,gBAAgB,eAAe,KAAK,eAAc,CAAE,EAAE,eAAe,KAAK,mBAAkB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAC/F,mBAAmB,eAAe,KAAK,kBAAiB,CAAE,EAAE,eAAe,KAAK,sBAAqB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CACxG,gBAAgB,eAAe,KAAK,eAAc,CAAE,EAAE,eAAe,KAAK,mBAAkB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAQjG,WAAW,gBAAgB,wBAAuB,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAEhD,OAAO,eAA2C,CACnE,GAAG,KAAK,YAAW,GACnB,GAAG,KAAK,SAAQ,CAAE,CAAC,KAAI,UAAS;EAC9B,QAAQ,KAAK,OAAM;EACnB,MAAM,KAAK,KAAI;EACf,gBAAgB,KAAK,eAAc;EACnC,SAAS,KAAK;CACf,EAAC,CACH,GAAC,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEiB,aAAa,OAAqB,QAAO,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CACzC,mBAAmB,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CAKzC,cAAc,MAAa;EACnC,KAAK,WAAW,IAAI,OAAO,SAAS,MAAM;CAC5C;CAEU,cAAc,QAAmC;EACzD,KAAK,iBAAiB,IAAI,OAAO,IAAI;CACvC;CAzFW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAmB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAnB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAmB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,qBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,mBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,uBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,uBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,oBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,uBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,oBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WA2CkB;IAA8B,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAChC;IAA4B,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WACxB;IAAgC,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAChC;IAAgC,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WACnC;IAA6B,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAC1B;IAAgC,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WACnC;IAA6B,aAAA;IAAA,UAAA;GAAA;GAAA;IAAA,cAAA;IAAA,WAgBhC;IAAsB,UAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UClIpE;EAkDA,QAAA,CAAA,qrEAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MDQI;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,aAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAuB,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAwB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,aAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAsB,UAAA;IAAA,QAAA,CAAA,OAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAC3F;IAA0B,UAAA;IAAA,QAAA,CAAA,eAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAA8B,UAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAKjD,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAmB,YAAA,CAAA;EAZ/B,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAa,YACX;GAAI,iBACC,wBAAwB;GAAM,SACtC;IACP;IACA;IAAkB;IAAyB;IAA0B;IACrE;IAA4B;GAC7B;GAAA,UAAA;GAAA,QAAA,CAAA,qrEAAA;EAAA,CAAA;CA+C+C,CAAA;CAAA,gBAAA;EAAA,OAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,qBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,mBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,uBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,uBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,oBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,uBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,oBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,iBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAAA,8BAA8B,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,eAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAChC,4BAA4B,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,mBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBACxB,gCAAgC,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,mBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAChC,gCAAgC,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,gBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBACnC,6BAA6B,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,mBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAC1B,gCAAgC,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,gBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBACnC,6BAA6B,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,UAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAgBhC,sBAAsB,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;CAAA;AAAA,CAAA"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { InjectionToken } from "@angular/core";
|
|
2
2
|
const SPARK_CONFIG = new InjectionToken("SPARK_CONFIG");
|
|
3
|
-
const defaultSparkConfig = {
|
|
3
|
+
const defaultSparkConfig = {
|
|
4
|
+
baseUrl: "/spark",
|
|
5
|
+
conflictDialog: { showChangedBy: false }
|
|
6
|
+
};
|
|
4
7
|
const SPARK_AUTH_STATE = new InjectionToken("SPARK_AUTH_STATE");
|
|
5
8
|
function provideSpark(config) {
|
|
6
9
|
return [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark.mjs","names":[],"sources":["../../src/lib/spark-config.ts","../../src/lib/spark-auth-state.ts","../../src/lib/provide-spark.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport interface SparkConfig {\n baseUrl: string;\n}\n\nexport const SPARK_CONFIG = new InjectionToken<SparkConfig>('SPARK_CONFIG');\n\nexport const defaultSparkConfig: SparkConfig = {\n baseUrl: '/spark'
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark.mjs","names":[],"sources":["../../src/lib/spark-config.ts","../../src/lib/spark-auth-state.ts","../../src/lib/provide-spark.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport interface SparkConfig {\n baseUrl: string;\n /**\n * The concurrency-conflict notice and dialog on the edit page.\n *\n * `showChangedBy`: when true, \"Changed by X\" names whoever wrote the version merged against, but\n * only when History resolves a display name for exactly that version (a `History/T` holder; one\n * `POST /spark/po/revisions` request). Default false: no History request is made and no user is\n * shown. A raw `ModifiedBy` user id is never shown in either mode. The \"at T\" time part is shown\n * whenever the object carries `ModifiedAt`.\n */\n conflictDialog?: { showChangedBy?: boolean };\n}\n\nexport const SPARK_CONFIG = new InjectionToken<SparkConfig>('SPARK_CONFIG');\n\nexport const defaultSparkConfig: SparkConfig = {\n baseUrl: '/spark',\n conflictDialog: { showChangedBy: false },\n};\n","import { InjectionToken, Signal } from '@angular/core';\n\n/**\n * A signal that changes whenever the authenticated user changes — the bridge that lets ng-spark\n * components react to sign-in/out without a dependency on `@mintplayer/ng-spark-auth` (no\n * dependency exists between the two packages, in either direction, on purpose).\n *\n * `@mintplayer/ng-spark-auth`'s `provideSparkAuth()` supplies it from `SparkAuthService.user`;\n * an app with its own auth stack provides any signal that changes on sign-in/out. Consumers\n * inject it `{ optional: true }` — absent, auth-sensitive data (the program-units menu) is\n * fetched once and never re-fetched.\n *\n * The signal's VALUE is deliberately opaque (`unknown`): consumers only track it for change,\n * never read it — what \"the user\" looks like belongs to the auth package.\n */\nexport const SPARK_AUTH_STATE = new InjectionToken<Signal<unknown>>('SPARK_AUTH_STATE');\n","import { Provider } from '@angular/core';\nimport { SPARK_CONFIG, SparkConfig, defaultSparkConfig } from './spark-config';\n\nexport function provideSpark(config?: Partial<SparkConfig>): Provider[] {\n return [\n {\n provide: SPARK_CONFIG,\n useValue: { ...defaultSparkConfig, ...config }\n }\n ];\n}\n"],"mappings":";AAgBA,MAAa,eAAe,IAAI,eAA4B,cAAc;AAE1E,MAAa,qBAAkC;CAC7C,SAAS;CACT,gBAAgB,EAAE,eAAe,MAAK;AACvC;ACND,MAAa,mBAAmB,IAAI,eAAgC,kBAAkB;ACZtF,SAAgB,aAAa,QAA6B;CACxD,OAAO,CACL;EACE,SAAS;EACT,UAAU;GAAE,GAAG;GAAoB,GAAG;EAAM;CAC7C,CACF;AACH"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintplayer/ng-spark",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "22.
|
|
4
|
+
"version": "22.25.0",
|
|
5
5
|
"description": "Angular component library for MintPlayer.Spark CRUD applications",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"@angular/common": "^22.0.0",
|
|
15
15
|
"@angular/router": "^22.0.0",
|
|
16
16
|
"@angular/forms": "^22.0.0",
|
|
17
|
-
"@mintplayer/ng-bootstrap": "^22.
|
|
17
|
+
"@mintplayer/ng-bootstrap": "^22.20.0",
|
|
18
|
+
"@mintplayer/web-components": "^2.17.0",
|
|
18
19
|
"@mintplayer/pagination": "*",
|
|
19
20
|
"rxjs": "~7.8.0"
|
|
20
21
|
},
|
|
@@ -41,6 +42,10 @@
|
|
|
41
42
|
"types": "./types/mintplayer-ng-spark-column-filter.d.ts",
|
|
42
43
|
"default": "./fesm2022/mintplayer-ng-spark-column-filter.mjs"
|
|
43
44
|
},
|
|
45
|
+
"./contributions": {
|
|
46
|
+
"types": "./types/mintplayer-ng-spark-contributions.d.ts",
|
|
47
|
+
"default": "./fesm2022/mintplayer-ng-spark-contributions.mjs"
|
|
48
|
+
},
|
|
44
49
|
"./grid": {
|
|
45
50
|
"types": "./types/mintplayer-ng-spark-grid.d.ts",
|
|
46
51
|
"default": "./fesm2022/mintplayer-ng-spark-grid.mjs"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PersistentObject } from "@mintplayer/ng-spark/models";
|
|
1
|
+
import { PersistentObject, TranslatedString } from "@mintplayer/ng-spark/models";
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
import { EnvironmentProviders, InjectionToken } from "@angular/core";
|
|
4
4
|
export declare enum NotificationKind {
|
|
@@ -15,7 +15,13 @@ export interface NavigateOperation {
|
|
|
15
15
|
}
|
|
16
16
|
export interface NotifyOperation {
|
|
17
17
|
type: 'notify';
|
|
18
|
+
/** The text in the request's language (the browser's `Accept-Language`). */
|
|
18
19
|
message: string;
|
|
20
|
+
/**
|
|
21
|
+
* The text in every language, when the server has it. Shown in the language the user picked in
|
|
22
|
+
* the app (`SparkLanguageService`), which the server never learns; `message` is the fallback.
|
|
23
|
+
*/
|
|
24
|
+
translatedMessage?: TranslatedString | null;
|
|
19
25
|
kind: NotificationKind;
|
|
20
26
|
durationMs?: number;
|
|
21
27
|
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { EntityAttributeDefinition, PersistentObject, SparkQuery } from "@mintplayer/ng-spark/models";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import { Provider } from "@angular/core";
|
|
4
|
+
import { SparkService } from "@mintplayer/ng-spark/services";
|
|
5
|
+
import { SparkDetailContext, SparkQueryRowAction } from "@mintplayer/ng-spark/panels";
|
|
6
|
+
import { SparkAttributeRendererRegistration } from "@mintplayer/ng-spark/renderers";
|
|
7
|
+
/** One line of a line diff: unchanged, only in the new text, or only in the old one. */
|
|
8
|
+
export interface SparkDiffLine {
|
|
9
|
+
kind: 'same' | 'added' | 'removed';
|
|
10
|
+
text: string;
|
|
11
|
+
}
|
|
12
|
+
/** Splits a text into lines (`\r\n`, `\r` and `\n` alike); an empty or absent text has none. */
|
|
13
|
+
export declare function splitLines(text: string | null | undefined): string[];
|
|
14
|
+
/**
|
|
15
|
+
* A line diff of `newText` against `oldText`: the longest common subsequence of their lines kept as
|
|
16
|
+
* `same`, everything else `removed` (old) or `added` (new), in reading order — at a change, the old
|
|
17
|
+
* lines come before the new ones. Pure, no dependency.
|
|
18
|
+
*
|
|
19
|
+
* Beyond {@link MAX_CELLS} cells (thousands of lines on both sides) the common prefix and suffix are
|
|
20
|
+
* still matched, and the middle is reported as removed-then-added rather than building a huge table.
|
|
21
|
+
*/
|
|
22
|
+
export declare function lineDiff(oldText: string | null | undefined, newText: string | null | undefined): SparkDiffLine[];
|
|
23
|
+
/** Whether a diff changes anything. */
|
|
24
|
+
export declare function diffHasChanges(lines: readonly SparkDiffLine[]): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Where the `lineDiff` renderer finds the text to compare with — its `rendererOptions`:
|
|
27
|
+
*
|
|
28
|
+
* - `compareType`: the model name (or alias, or id) of the object to load;
|
|
29
|
+
* - its id: `compareIdAttribute` (an attribute of this object holding it), or
|
|
30
|
+
* `compareIdPattern` + `compareIdReplacement` (a regular expression and replacement applied to this
|
|
31
|
+
* object's id);
|
|
32
|
+
* - `compareAttribute`: the attribute of that object holding the text — or, for an AsDetail list, the
|
|
33
|
+
* list, with `compareRowKeyPattern` + `compareRowKeyReplacement` (deriving the row key from this
|
|
34
|
+
* object's id) and `compareRowAttribute` (the text on the row); for a single AsDetail object,
|
|
35
|
+
* `compareRowAttribute` alone.
|
|
36
|
+
*
|
|
37
|
+
* Contributions seeds these on a generated contribution type's text values, comparing against the
|
|
38
|
+
* target's row of the same slot (the current version).
|
|
39
|
+
*/
|
|
40
|
+
export interface SparkLineDiffSource {
|
|
41
|
+
type: string;
|
|
42
|
+
id: string;
|
|
43
|
+
attribute: string;
|
|
44
|
+
rowKey?: string;
|
|
45
|
+
rowAttribute?: string;
|
|
46
|
+
}
|
|
47
|
+
/** The comparison source for `item`, or null when the options do not describe one. */
|
|
48
|
+
export declare function lineDiffSourceOf(options: Record<string, any> | null | undefined, item: PersistentObject | null | undefined): SparkLineDiffSource | null;
|
|
49
|
+
/** The text at `source` in the loaded object, or null when it is not there (or not readable). */
|
|
50
|
+
export declare function lineDiffTextOf(po: PersistentObject | null | undefined, source: SparkLineDiffSource): string | null;
|
|
51
|
+
/**
|
|
52
|
+
* The generic `lineDiff` detail renderer: this attribute's text, diffed line by line against a text
|
|
53
|
+
* elsewhere ({@link SparkLineDiffSource}) — added lines marked `+`, removed ones `−`. When the other
|
|
54
|
+
* object cannot be read (no right, gone), the text is shown as it is, with a note.
|
|
55
|
+
*
|
|
56
|
+
* Register through `sparkContributionRenderers` (or on its own: `{ name: 'lineDiff', detailComponent:
|
|
57
|
+
* SparkLineDiffComponent }`).
|
|
58
|
+
*/
|
|
59
|
+
export declare class SparkLineDiffComponent {
|
|
60
|
+
private readonly spark;
|
|
61
|
+
value: import("@angular/core").InputSignal<any>;
|
|
62
|
+
attribute: import("@angular/core").InputSignal<EntityAttributeDefinition | undefined>;
|
|
63
|
+
options: import("@angular/core").InputSignal<Record<string, any> | undefined>;
|
|
64
|
+
item: import("@angular/core").InputSignal<PersistentObject | undefined>;
|
|
65
|
+
protected readonly text: import("@angular/core").Signal<string>;
|
|
66
|
+
/** The compared text: undefined while loading, null when it could not be read. */
|
|
67
|
+
private readonly compared;
|
|
68
|
+
protected readonly state: import("@angular/core").Signal<"loading" | "diff" | "unavailable">;
|
|
69
|
+
protected readonly lines: import("@angular/core").Signal<SparkDiffLine[]>;
|
|
70
|
+
protected readonly changed: import("@angular/core").Signal<boolean>;
|
|
71
|
+
private generation;
|
|
72
|
+
constructor();
|
|
73
|
+
protected marker(line: SparkDiffLine): string;
|
|
74
|
+
private load;
|
|
75
|
+
/** The entity type id for a model name or alias (the load endpoint is keyed by the type's id). */
|
|
76
|
+
private typeIdOf;
|
|
77
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkLineDiffComponent, never>;
|
|
78
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkLineDiffComponent, "spark-line-diff", never, {
|
|
79
|
+
"value": {
|
|
80
|
+
"alias": "value";
|
|
81
|
+
"required": false;
|
|
82
|
+
"isSignal": true;
|
|
83
|
+
};
|
|
84
|
+
"attribute": {
|
|
85
|
+
"alias": "attribute";
|
|
86
|
+
"required": false;
|
|
87
|
+
"isSignal": true;
|
|
88
|
+
};
|
|
89
|
+
"options": {
|
|
90
|
+
"alias": "options";
|
|
91
|
+
"required": false;
|
|
92
|
+
"isSignal": true;
|
|
93
|
+
};
|
|
94
|
+
"item": {
|
|
95
|
+
"alias": "item";
|
|
96
|
+
"required": false;
|
|
97
|
+
"isSignal": true;
|
|
98
|
+
};
|
|
99
|
+
}, {}, never, never, true, never>;
|
|
100
|
+
}
|
|
101
|
+
/** The `rendererOptions` Contributions writes on each attribution attribute (library README, "Client contract"). */
|
|
102
|
+
export interface SparkContributionAttributionOptions {
|
|
103
|
+
/** The generated contributions query's alias (`songlyricscontributions`). */
|
|
104
|
+
contributionsQuery: string;
|
|
105
|
+
/** The target's model name: the query's `parentType` (`Song`). */
|
|
106
|
+
targetType: string;
|
|
107
|
+
/** The `[Contribution]` property (`Lyrics`). */
|
|
108
|
+
property: string;
|
|
109
|
+
/** The slot attributes, in id order: one column filter each (`Language`, `Script`). */
|
|
110
|
+
slots: string[];
|
|
111
|
+
/** The attribution attributes the row carries: `ContributorName`, `UpdatedAt`, `ContributionCount`. */
|
|
112
|
+
attribution: string[];
|
|
113
|
+
}
|
|
114
|
+
/** The History link of a row: `/query/{contributionsQuery}?parentId=…&parentType=…&{slot}=…`. */
|
|
115
|
+
export interface SparkContributionHistoryLink {
|
|
116
|
+
commands: string[];
|
|
117
|
+
queryParams: Record<string, string>;
|
|
118
|
+
}
|
|
119
|
+
/** The History link for `row` of the object `ownerId`, or null when either is missing. */
|
|
120
|
+
export declare function contributionHistoryLink(options: Partial<SparkContributionAttributionOptions> | null | undefined, row: Record<string, any> | null | undefined, ownerId: string | null | undefined): SparkContributionHistoryLink | null;
|
|
121
|
+
/** "3 days ago" in `language`, from an ISO instant; null when it does not parse. */
|
|
122
|
+
export declare function relativeTime(value: unknown, language: string, now?: number): string | null;
|
|
123
|
+
/**
|
|
124
|
+
* The `contributionAttribution` AsDetail **row** renderer (contributions PRD Q6): one line under a
|
|
125
|
+
* row — "by Alice · 3 days ago · History (4)" — instead of three columns. Only the parts the
|
|
126
|
+
* declaration asked for (`rendererOptions.attribution`) and that the row has; History links to the
|
|
127
|
+
* slot's contributions query (`/query/{contributionsQuery}` with the parent and one filter per slot).
|
|
128
|
+
*/
|
|
129
|
+
export declare class SparkContributionAttributionComponent {
|
|
130
|
+
private readonly lang;
|
|
131
|
+
row: import("@angular/core").InputSignal<Record<string, any>>;
|
|
132
|
+
options: import("@angular/core").InputSignal<Record<string, any> | undefined>;
|
|
133
|
+
ownerId: import("@angular/core").InputSignal<string | undefined>;
|
|
134
|
+
private readonly asked;
|
|
135
|
+
protected readonly historyLink: import("@angular/core").Signal<SparkContributionHistoryLink | null>;
|
|
136
|
+
protected readonly parts: import("@angular/core").Signal<{
|
|
137
|
+
kind: "by" | "at" | "history";
|
|
138
|
+
text: string;
|
|
139
|
+
iso?: string;
|
|
140
|
+
title?: string;
|
|
141
|
+
}[]>;
|
|
142
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkContributionAttributionComponent, never>;
|
|
143
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkContributionAttributionComponent, "spark-contribution-attribution", never, {
|
|
144
|
+
"row": {
|
|
145
|
+
"alias": "row";
|
|
146
|
+
"required": false;
|
|
147
|
+
"isSignal": true;
|
|
148
|
+
};
|
|
149
|
+
"options": {
|
|
150
|
+
"alias": "options";
|
|
151
|
+
"required": false;
|
|
152
|
+
"isSignal": true;
|
|
153
|
+
};
|
|
154
|
+
"ownerId": {
|
|
155
|
+
"alias": "ownerId";
|
|
156
|
+
"required": false;
|
|
157
|
+
"isSignal": true;
|
|
158
|
+
};
|
|
159
|
+
}, {}, never, never, true, never>;
|
|
160
|
+
}
|
|
161
|
+
/** The source of every generated `{Target}{Property}Contributions` query (`ContributionDescriptor.ContributionsQueryMethod`). */
|
|
162
|
+
export declare const SPARK_CONTRIBUTIONS_QUERY_SOURCE = "Custom.SparkContributionsOfTarget";
|
|
163
|
+
/** `POST /spark/po/revert-contribution` (the Contributions server package). */
|
|
164
|
+
export declare const SPARK_REVERT_CONTRIBUTION_PATH = "/po/revert-contribution";
|
|
165
|
+
/** Whether `query` is a generated contributions query (its rows are contributions). */
|
|
166
|
+
export declare function isContributionsQuery(query: Pick<SparkQuery, 'source'> | null | undefined): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Makes a contribution current again: every newer visible version of its slot is hidden (reason
|
|
169
|
+
* `reverted`), atomically, by the server. The response's notice ("…newer version(s) were hidden") is
|
|
170
|
+
* dispatched like every operation. Rejects with the server's error (400 "restore it first" for a
|
|
171
|
+
* hidden one, 404 without the right).
|
|
172
|
+
*/
|
|
173
|
+
export declare function revertContribution(spark: SparkService, objectTypeId: string, id: string): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* "Revert to this version" in the row menu of a contributions query — for holders of
|
|
176
|
+
* `RevertContribution/{type}`, outside the recycle bin. Asks first; refreshes the list afterwards.
|
|
177
|
+
*/
|
|
178
|
+
export declare const sparkRevertContributionRowAction: SparkQueryRowAction;
|
|
179
|
+
/**
|
|
180
|
+
* "Revert to this version" on a contribution's detail page (a `SPARK_DETAIL_ACTIONS` entry): shown for
|
|
181
|
+
* `RevertContribution/{type}` holders on a generated contribution type (one that has the generated
|
|
182
|
+
* contributions query), outside the recycle bin. Reloads the page afterwards.
|
|
183
|
+
*/
|
|
184
|
+
export declare class SparkRevertContributionComponent {
|
|
185
|
+
private readonly spark;
|
|
186
|
+
private readonly lang;
|
|
187
|
+
context: import("@angular/core").InputSignal<SparkDetailContext>;
|
|
188
|
+
/** Whether the type is a generated contribution type: it has the generated contributions query. */
|
|
189
|
+
private readonly isContributionType;
|
|
190
|
+
protected readonly offered: import("@angular/core").Signal<boolean>;
|
|
191
|
+
protected readonly busy: import("@angular/core").WritableSignal<boolean>;
|
|
192
|
+
protected readonly error: import("@angular/core").WritableSignal<string | null>;
|
|
193
|
+
constructor();
|
|
194
|
+
revert(): Promise<void>;
|
|
195
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkRevertContributionComponent, never>;
|
|
196
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkRevertContributionComponent, "spark-revert-contribution", never, {
|
|
197
|
+
"context": {
|
|
198
|
+
"alias": "context";
|
|
199
|
+
"required": true;
|
|
200
|
+
"isSignal": true;
|
|
201
|
+
};
|
|
202
|
+
}, {}, never, never, true, never>;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Adds the Contributions UI to the pages `sparkRoutes()` routes to — no routes of its own (PRD Q7):
|
|
206
|
+
* "Revert to this version" in the contributions query's row menu and on a contribution's detail page.
|
|
207
|
+
* Needs the server package `MintPlayer.Spark.Contributions`.
|
|
208
|
+
*
|
|
209
|
+
* ```ts
|
|
210
|
+
* providers: [
|
|
211
|
+
* provideSpark(...),
|
|
212
|
+
* provideSparkContributions(),
|
|
213
|
+
* provideSparkAttributeRenderers([...sparkContributionRenderers, ...yourRenderers]),
|
|
214
|
+
* ]
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* The renderers are registered with the app's own, because `provideSparkAttributeRenderers` takes one
|
|
218
|
+
* list: see {@link sparkContributionRenderers}.
|
|
219
|
+
*/
|
|
220
|
+
export declare function provideSparkContributions(options?: {
|
|
221
|
+
detailActionPriority?: number;
|
|
222
|
+
}): Provider[];
|
|
223
|
+
/**
|
|
224
|
+
* The two renderers the Contributions model names:
|
|
225
|
+
*
|
|
226
|
+
* - `contributionAttribution` — an AsDetail **row** renderer: "by Alice · 3 days ago · History (4)"
|
|
227
|
+
* once per row, in place of the `ContributorName`/`UpdatedAt`/`ContributionCount` columns;
|
|
228
|
+
* - `lineDiff` — a detail renderer, generic: a text diffed line by line against a text of another
|
|
229
|
+
* object (Contributions seeds it on a contribution's text values, against the current version).
|
|
230
|
+
*/
|
|
231
|
+
export declare const sparkContributionRenderers: SparkAttributeRendererRegistration[];
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { BsDatatableFetch, BsDatatableRowEvent, DatatableDistincts, DatatableSettings, FilterChangeDetail } from "@mintplayer/ng-bootstrap/datatable";
|
|
2
|
-
import { CustomActionDefinition, EntityAttributeDefinition, EntityPermissions, EntityType, LookupReference, PersistentObject, QueryColumn, QueryResultItem, SparkCellColumn, SparkDeletedFilter, SparkQuery, SparkSelectionModeSetting } from "@mintplayer/ng-spark/models";
|
|
2
|
+
import { CustomActionDefinition, EntityAttributeDefinition, EntityPermissions, EntityType, LookupReference, PersistentObject, QueryColumn, QueryColumnFilter, QueryResultItem, SparkCellColumn, SparkDeletedFilter, SparkQuery, SparkSelectionModeSetting } from "@mintplayer/ng-spark/models";
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
import { TemplateRef, Type } from "@angular/core";
|
|
5
5
|
import { HttpErrorResponse } from "@angular/common/http";
|
|
6
6
|
import { Color } from "@mintplayer/ng-bootstrap";
|
|
7
7
|
import { ConnectedPosition } from "@angular/cdk/overlay";
|
|
8
8
|
import { SparkLanguageService } from "@mintplayer/ng-spark/services";
|
|
9
|
+
import { SparkQueryRowAction } from "@mintplayer/ng-spark/panels";
|
|
9
10
|
import { ReferenceChip } from "@mintplayer/ng-spark/pipes";
|
|
10
11
|
/** Page sizes offered by every Spark grid. */
|
|
11
12
|
export declare const SPARK_GRID_PAGE_SIZES: number[];
|
|
@@ -206,7 +207,9 @@ export declare class SparkQueryActionsContext {
|
|
|
206
207
|
* actions, enabled by the same rules.
|
|
207
208
|
*/
|
|
208
209
|
export interface SparkQueryToolbarAction {
|
|
209
|
-
kind: 'new' | 'delete' | 'custom';
|
|
210
|
+
kind: 'new' | 'delete' | 'custom' | 'addon';
|
|
211
|
+
/** For `addon` (row menu only): the add-on's entry (`SPARK_QUERY_ROW_ACTIONS`). */
|
|
212
|
+
addon?: SparkQueryRowAction;
|
|
210
213
|
/** The action's name, unique within the toolbar. */
|
|
211
214
|
name: string;
|
|
212
215
|
/** Its catalogue entry: label, icon, `selectionRule`, `variant`, confirmation. */
|
|
@@ -253,6 +256,9 @@ export declare class SparkQueryGridComponent {
|
|
|
253
256
|
private readonly sparkService;
|
|
254
257
|
private readonly gridRenderers;
|
|
255
258
|
private readonly queryRefresh;
|
|
259
|
+
private readonly injector;
|
|
260
|
+
/** Add-on row-menu entries (`SPARK_QUERY_ROW_ACTIONS`), e.g. Contributions' revert. */
|
|
261
|
+
private readonly addonRowActions;
|
|
256
262
|
readonly lang: SparkLanguageService;
|
|
257
263
|
/** Query alias or id. */
|
|
258
264
|
queryId: import("@angular/core").InputSignal<string>;
|
|
@@ -270,6 +276,16 @@ export declare class SparkQueryGridComponent {
|
|
|
270
276
|
*/
|
|
271
277
|
parentId: import("@angular/core").InputSignal<string>;
|
|
272
278
|
parentType: import("@angular/core").InputSignal<string>;
|
|
279
|
+
/**
|
|
280
|
+
* Column filters in force from the first fetch on — the query page's URL filters, e.g. the
|
|
281
|
+
* contributions History link's `?Language=en&Script=Latn`. Only those naming an attribute of the
|
|
282
|
+
* query's entity type are applied ({@link applicablePresetFilters}); see {@link appliedPresetFilters}.
|
|
283
|
+
* A change replaces the previous preset (filters the user set in a column panel on other columns
|
|
284
|
+
* stay) and refetches from page 1.
|
|
285
|
+
*/
|
|
286
|
+
presetFilters: import("@angular/core").InputSignal<readonly QueryColumnFilter[]>;
|
|
287
|
+
/** The preset filters actually applied, for a host to show (and offer to clear). */
|
|
288
|
+
readonly appliedPresetFilters: import("@angular/core").WritableSignal<QueryColumnFilter[]>;
|
|
273
289
|
/**
|
|
274
290
|
* Rows supplied from outside. When bound, the grid renders these and runs no fetch.
|
|
275
291
|
*
|
|
@@ -459,6 +475,8 @@ export declare class SparkQueryGridComponent {
|
|
|
459
475
|
* left to the toolbar.
|
|
460
476
|
*/
|
|
461
477
|
rowActions: import("@angular/core").Signal<SparkQueryToolbarAction[]>;
|
|
478
|
+
/** What an add-on row action is asked whether it is offered; null until the type resolved. */
|
|
479
|
+
private readonly rowActionScope;
|
|
462
480
|
/** The default Delete: not withheld by the result, and never in the recycle bin. */
|
|
463
481
|
private offersDelete;
|
|
464
482
|
/** Whether a toolbar action can run with the current selection. The server checks again. */
|
|
@@ -493,6 +511,8 @@ export declare class SparkQueryGridComponent {
|
|
|
493
511
|
* the menu is a shortcut for this row, not a second way to tick it.
|
|
494
512
|
*/
|
|
495
513
|
runRowAction(action: SparkQueryToolbarAction, row: QueryResultItem): Promise<void>;
|
|
514
|
+
/** An add-on row action, in this grid's injection context; a failure lands in the grid's alert. */
|
|
515
|
+
private runAddonRowAction;
|
|
496
516
|
/**
|
|
497
517
|
* New from this grid: the create page, carrying the sub-query's parent (#460, D19) as query
|
|
498
518
|
* parameters so it survives the navigation and a reload of the create page. The server's
|
|
@@ -666,6 +686,11 @@ export declare class SparkQueryGridComponent {
|
|
|
666
686
|
"required": false;
|
|
667
687
|
"isSignal": true;
|
|
668
688
|
};
|
|
689
|
+
"presetFilters": {
|
|
690
|
+
"alias": "presetFilters";
|
|
691
|
+
"required": false;
|
|
692
|
+
"isSignal": true;
|
|
693
|
+
};
|
|
669
694
|
"data": {
|
|
670
695
|
"alias": "data";
|
|
671
696
|
"required": false;
|
|
@@ -1070,4 +1095,11 @@ export declare class SparkSearchBoxComponent {
|
|
|
1070
1095
|
}, {
|
|
1071
1096
|
"term": "termChange";
|
|
1072
1097
|
}, never, never, true, never>;
|
|
1073
|
-
}
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* The preset column filters (a query page's URL filters) that name an attribute of the query's
|
|
1101
|
+
* entity type, with their values coerced to the attribute's type — a URL carries only strings, and
|
|
1102
|
+
* the server compares a number column against numbers. Filters naming anything else are dropped, so
|
|
1103
|
+
* an unrelated query-string parameter never becomes a request.
|
|
1104
|
+
*/
|
|
1105
|
+
export declare function applicablePresetFilters(filters: readonly QueryColumnFilter[] | null | undefined, entityType: EntityType | null | undefined): QueryColumnFilter[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityAttributeDefinition, EntityPermissions, EntityType, PersistentObject, PersistentObjectAttribute, QueryColumn, SparkDeletedFilter } from "@mintplayer/ng-spark/models";
|
|
1
|
+
import { EntityAttributeDefinition, EntityPermissions, EntityType, PersistentObject, PersistentObjectAttribute, QueryColumn, SparkDeletedFilter, comparableValue } from "@mintplayer/ng-spark/models";
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
import { Provider } from "@angular/core";
|
|
4
4
|
import { Color } from "@mintplayer/ng-bootstrap";
|
|
@@ -60,14 +60,6 @@ export interface SparkRevisionChange {
|
|
|
60
60
|
* attributes are simply absent from what the server sends, so they never appear as a difference.
|
|
61
61
|
*/
|
|
62
62
|
export declare function revisionAttributes(entityType: EntityType | null | undefined): EntityAttributeDefinition[];
|
|
63
|
-
/**
|
|
64
|
-
* A comparable form of an attribute's content.
|
|
65
|
-
*
|
|
66
|
-
* Nested objects (AsDetail rows, references rendered as objects) are reduced to their attributes'
|
|
67
|
-
* values: their envelopes carry per-read fields (etags, breadcrumbs, row keys) that differ between two
|
|
68
|
-
* reads of identical content and would report every AsDetail attribute as changed.
|
|
69
|
-
*/
|
|
70
|
-
export declare function comparableValue(attribute: PersistentObjectAttribute | undefined): string;
|
|
71
63
|
/** The shown attributes whose content differs between `revision` and `current`, in display order. */
|
|
72
64
|
export declare function diffRevision(entityType: EntityType | null | undefined, revision: PersistentObject | null | undefined, current: PersistentObject | null | undefined): SparkRevisionChange[];
|
|
73
65
|
type HistoryView = 'view' | 'diff';
|
|
@@ -220,4 +212,5 @@ export declare class SparkHistoryPanelComponent {
|
|
|
220
212
|
*/
|
|
221
213
|
export declare function provideSparkHistory(options?: {
|
|
222
214
|
order?: number;
|
|
223
|
-
}): Provider[];
|
|
215
|
+
}): Provider[];
|
|
216
|
+
export { comparableValue };
|