@konce-pt/angular 0.7.12 → 0.8.1

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.
@@ -1,10 +1,16 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { input, booleanAttribute, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, model, output, signal, Injectable, inject, ElementRef, effect, InjectionToken, PLATFORM_ID, DestroyRef, makeEnvironmentProviders, contentChild, afterNextRender, untracked, forwardRef, numberAttribute, viewChild, Directive, TemplateRef, Injector, viewChildren, contentChildren, afterRenderEffect, linkedSignal } from '@angular/core';
3
3
  import { CdkOverlayOrigin, CdkConnectedOverlay, OverlayContainer } from '@angular/cdk/overlay';
4
+ import { KPT_ICONS, sanitizeSvgFragment, renderKptIconSvg } from '@konce-pt/icons';
5
+ export { renderKptIconSvg } from '@konce-pt/icons';
6
+ import { KPT_MESSAGES_EN, KPT_MESSAGES_PL, deepMerge, translate, weekdayNames, monthNames } from '@konce-pt/i18n';
7
+ export { KPT_MESSAGES_EN, KPT_MESSAGES_PL } from '@konce-pt/i18n';
4
8
  import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
9
+ import { pad, hourMarks, minuteMarks, handAngle, handIsInner, parseTime, from12h, hourFromAngle, minuteFromAngle, commitLevelFor, decadeStart, centuryStart, canPageBack, canPageForward, formatTime, buildDayGrid, toIso, selectedYearMonth, buildMonthCells, buildYearCells, buildDecadeCells, initialPage, resolveStartView, parseDateTime, formatDate, KPT_CALENDAR_LEVELS, pageBy, clampVisibleMonths, datePart, timePart, buildRangeGrid, pickRangeDay } from '@konce-pt/datetime';
5
10
  import { form, required, email, minLength, validateTree, submit, FormField, FormRoot } from '@angular/forms/signals';
11
+ import { toText, aggregate, escapeCsvCell, isEmptyFilterValue, matchesColumnFilter } from '@konce-pt/table';
6
12
 
7
- const _c0$E = ["*"];
13
+ const _c0$F = ["*"];
8
14
  function KptButton_Conditional_1_Template(rf, ctx) { if (rf & 1) {
9
15
  i0.ɵɵdomElement(0, "span", 1);
10
16
  } }
@@ -39,7 +45,7 @@ class KptButton {
39
45
  static { this.ɵfac = function KptButton_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptButton)(); }; }
40
46
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptButton, selectors: [["kpt-button"]], hostAttrs: [1, "kpt-button-host"], hostVars: 2, hostBindings: function KptButton_HostBindings(rf, ctx) { if (rf & 2) {
41
47
  i0.ɵɵclassProp("kpt-button-host--full", ctx.fullWidth());
42
- } }, inputs: { variant: [1, "variant"], size: [1, "size"], type: [1, "type"], disabled: [1, "disabled"], loading: [1, "loading"], fullWidth: [1, "fullWidth"] }, ngContentSelectors: _c0$E, decls: 4, vars: 8, consts: [[1, "kpt-button", 3, "type", "disabled"], ["aria-hidden", "true", 1, "kpt-button__spinner"], [1, "kpt-button__content"]], template: function KptButton_Template(rf, ctx) { if (rf & 1) {
48
+ } }, inputs: { variant: [1, "variant"], size: [1, "size"], type: [1, "type"], disabled: [1, "disabled"], loading: [1, "loading"], fullWidth: [1, "fullWidth"] }, ngContentSelectors: _c0$F, decls: 4, vars: 8, consts: [[1, "kpt-button", 3, "type", "disabled"], ["aria-hidden", "true", 1, "kpt-button__spinner"], [1, "kpt-button__content"]], template: function KptButton_Template(rf, ctx) { if (rf & 1) {
43
49
  i0.ɵɵprojectionDef();
44
50
  i0.ɵɵdomElementStart(0, "button", 0);
45
51
  i0.ɵɵconditionalCreate(1, KptButton_Conditional_1_Template, 1, 0, "span", 1);
@@ -63,7 +69,7 @@ class KptButton {
63
69
  }], null, { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }] }); })();
64
70
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptButton, { className: "KptButton", filePath: "lib/button/button.component.ts", lineNumber: 32 }); })();
65
71
 
66
- const _c0$D = ["*"];
72
+ const _c0$E = ["*"];
67
73
  function KptIconButton_Conditional_1_Template(rf, ctx) { if (rf & 1) {
68
74
  i0.ɵɵdomElement(0, "span", 1);
69
75
  } }
@@ -92,18 +98,26 @@ class KptIconButton {
92
98
  /** Etykieta dostępności (wymagana — przycisk nie ma tekstu). */
93
99
  this.ariaLabel = input.required(/* @ts-ignore */
94
100
  ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
101
+ /**
102
+ * Stan wciśnięcia dla przycisku przełącznika (gwiazdka „w ulubionych", pauza, filtr).
103
+ * Musi zjechać na wewnętrzny `<button>`: `[attr.aria-pressed]` postawione na
104
+ * `<kpt-icon-button>` ląduje na hoście, który nie ma roli przycisku — czytnik nie ma
105
+ * wtedy czego ogłosić. `null` (domyślnie) nie wypisuje atrybutu w ogóle.
106
+ */
107
+ this.ariaPressed = input(null, /* @ts-ignore */
108
+ ...(ngDevMode ? [{ debugName: "ariaPressed" }] : /* istanbul ignore next */ []));
95
109
  this.isDisabled = computed(() => this.disabled() || this.loading(), /* @ts-ignore */
96
110
  ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
97
111
  }
98
112
  static { this.ɵfac = function KptIconButton_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptIconButton)(); }; }
99
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptIconButton, selectors: [["kpt-icon-button"]], hostAttrs: [1, "kpt-icon-button-host"], inputs: { variant: [1, "variant"], size: [1, "size"], shape: [1, "shape"], type: [1, "type"], disabled: [1, "disabled"], loading: [1, "loading"], ariaLabel: [1, "ariaLabel"] }, ngContentSelectors: _c0$D, decls: 3, vars: 8, consts: [[1, "kpt-icon-button", 3, "type", "disabled"], ["aria-hidden", "true", 1, "kpt-icon-button__spinner"]], template: function KptIconButton_Template(rf, ctx) { if (rf & 1) {
113
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptIconButton, selectors: [["kpt-icon-button"]], hostAttrs: [1, "kpt-icon-button-host"], inputs: { variant: [1, "variant"], size: [1, "size"], shape: [1, "shape"], type: [1, "type"], disabled: [1, "disabled"], loading: [1, "loading"], ariaLabel: [1, "ariaLabel"], ariaPressed: [1, "ariaPressed"] }, ngContentSelectors: _c0$E, decls: 3, vars: 9, consts: [[1, "kpt-icon-button", 3, "type", "disabled"], ["aria-hidden", "true", 1, "kpt-icon-button__spinner"]], template: function KptIconButton_Template(rf, ctx) { if (rf & 1) {
100
114
  i0.ɵɵprojectionDef();
101
115
  i0.ɵɵdomElementStart(0, "button", 0);
102
116
  i0.ɵɵconditionalCreate(1, KptIconButton_Conditional_1_Template, 1, 0, "span", 1)(2, KptIconButton_Conditional_2_Template, 1, 0);
103
117
  i0.ɵɵdomElementEnd();
104
118
  } if (rf & 2) {
105
119
  i0.ɵɵdomProperty("type", ctx.type())("disabled", ctx.isDisabled());
106
- i0.ɵɵattribute("data-variant", ctx.variant())("data-size", ctx.size())("data-shape", ctx.shape())("aria-label", ctx.ariaLabel())("aria-busy", ctx.loading() ? "true" : null);
120
+ i0.ɵɵattribute("data-variant", ctx.variant())("data-size", ctx.size())("data-shape", ctx.shape())("aria-label", ctx.ariaLabel())("aria-pressed", ctx.ariaPressed())("aria-busy", ctx.loading() ? "true" : null);
107
121
  i0.ɵɵadvance();
108
122
  i0.ɵɵconditional(ctx.loading() ? 1 : 2);
109
123
  } }, styles: ["@layer kpt.components{.kpt-icon-button-host{display:inline-flex}.kpt-icon-button{--%NS%_bg: transparent;--%NS%_fg: var(--%NS%kpt-color-on-surface);--%NS%_bg-hover: var(--%NS%kpt-color-muted);position:relative;isolation:isolate;display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border:var(--%NS%kpt-border-width-thin, 1px) solid transparent;border-radius:var(--%NS%kpt-radius-full, 9999px);background:var(--%NS%_bg);color:var(--%NS%_fg);cursor:pointer;font-size:1.25rem}.kpt-icon-button:after{content:\"\";position:absolute;inset:0;z-index:-1;border-radius:inherit;background-color:var(--%NS%_bg-hover);opacity:0;pointer-events:none;transition:opacity var(--%NS%kpt-motion-duration-fast, .12s) var(--%NS%kpt-motion-easing-standard)}.kpt-icon-button:hover:not(:disabled):after{opacity:1}.kpt-icon-button:disabled{cursor:not-allowed;opacity:.5}.kpt-icon-button[data-shape=square]{border-radius:var(--%NS%kpt-radius-md, .5rem)}.kpt-icon-button[data-size=sm]{width:2rem;height:2rem;font-size:1rem}.kpt-icon-button[data-size=lg]{width:3rem;height:3rem;font-size:1.5rem}.kpt-icon-button[data-variant=filled]{--%NS%_bg: var(--%NS%kpt-color-primary);--%NS%_fg: var(--%NS%kpt-color-on-primary);--%NS%_bg-hover: var(--%NS%kpt-color-primary-hover)}.kpt-icon-button[data-variant=tonal]{--%NS%_bg: var(--%NS%kpt-color-muted);--%NS%_fg: var(--%NS%kpt-color-on-muted);--%NS%_bg-hover: var(--%NS%kpt-color-muted-hover)}.kpt-icon-button[data-variant=outline]{border-color:var(--%NS%kpt-color-border-strong)}.kpt-icon-button[data-variant=danger]{--%NS%_bg: var(--%NS%kpt-color-danger);--%NS%_fg: var(--%NS%kpt-color-on-danger);--%NS%_bg-hover: color-mix(in oklch, var(--%NS%kpt-color-danger) 88%, black)}@media(prefers-reduced-motion:reduce){.kpt-icon-button:after{transition:none}}.kpt-icon-button__spinner{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:kpt-spinner-rotate .6s linear infinite}}\n"], encapsulation: 2 }); }
@@ -119,6 +133,7 @@ class KptIconButton {
119
133
  [attr.data-shape]="shape()"
120
134
  [disabled]="isDisabled()"
121
135
  [attr.aria-label]="ariaLabel()"
136
+ [attr.aria-pressed]="ariaPressed()"
122
137
  [attr.aria-busy]="loading() ? 'true' : null"
123
138
  >
124
139
  @if (loading()) {
@@ -128,8 +143,8 @@ class KptIconButton {
128
143
  }
129
144
  </button>
130
145
  `, host: { class: 'kpt-icon-button-host' }, styles: ["@layer kpt.components{.kpt-icon-button-host{display:inline-flex}.kpt-icon-button{--_bg: transparent;--_fg: var(--kpt-color-on-surface);--_bg-hover: var(--kpt-color-muted);position:relative;isolation:isolate;display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border:var(--kpt-border-width-thin, 1px) solid transparent;border-radius:var(--kpt-radius-full, 9999px);background:var(--_bg);color:var(--_fg);cursor:pointer;font-size:1.25rem}.kpt-icon-button:after{content:\"\";position:absolute;inset:0;z-index:-1;border-radius:inherit;background-color:var(--_bg-hover);opacity:0;pointer-events:none;transition:opacity var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard)}.kpt-icon-button:hover:not(:disabled):after{opacity:1}.kpt-icon-button:disabled{cursor:not-allowed;opacity:.5}.kpt-icon-button[data-shape=square]{border-radius:var(--kpt-radius-md, .5rem)}.kpt-icon-button[data-size=sm]{width:2rem;height:2rem;font-size:1rem}.kpt-icon-button[data-size=lg]{width:3rem;height:3rem;font-size:1.5rem}.kpt-icon-button[data-variant=filled]{--_bg: var(--kpt-color-primary);--_fg: var(--kpt-color-on-primary);--_bg-hover: var(--kpt-color-primary-hover)}.kpt-icon-button[data-variant=tonal]{--_bg: var(--kpt-color-muted);--_fg: var(--kpt-color-on-muted);--_bg-hover: var(--kpt-color-muted-hover)}.kpt-icon-button[data-variant=outline]{border-color:var(--kpt-color-border-strong)}.kpt-icon-button[data-variant=danger]{--_bg: var(--kpt-color-danger);--_fg: var(--kpt-color-on-danger);--_bg-hover: color-mix(in oklch, var(--kpt-color-danger) 88%, black)}@media(prefers-reduced-motion:reduce){.kpt-icon-button:after{transition:none}}.kpt-icon-button__spinner{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:kpt-spinner-rotate .6s linear infinite}}\n"] }]
131
- }], null, { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }] }); })();
132
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptIconButton, { className: "KptIconButton", filePath: "lib/icon-button/icon-button.component.ts", lineNumber: 36 }); })();
146
+ }], null, { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }], ariaPressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaPressed", required: false }] }] }); })();
147
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptIconButton, { className: "KptIconButton", filePath: "lib/icon-button/icon-button.component.ts", lineNumber: 37 }); })();
133
148
 
134
149
  const _forTrack0$e = ($index, $item) => $item.value;
135
150
  function KptButtonGroup_For_2_Template(rf, ctx) { if (rf & 1) {
@@ -203,7 +218,7 @@ class KptButtonGroup {
203
218
  }], null, { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }] }); })();
204
219
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptButtonGroup, { className: "KptButtonGroup", filePath: "lib/button-group/button-group.component.ts", lineNumber: 41 }); })();
205
220
 
206
- const _c0$C = ["*"];
221
+ const _c0$D = ["*"];
207
222
  /**
208
223
  * Floating Action Button (FAB) — okrągły, wyniesiony przycisk akcji. Wariant `extended` = pigułka z tekstem.
209
224
  *
@@ -226,7 +241,7 @@ class KptFab {
226
241
  ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
227
242
  }
228
243
  static { this.ɵfac = function KptFab_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptFab)(); }; }
229
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptFab, selectors: [["kpt-fab"]], hostAttrs: [1, "kpt-fab-host"], inputs: { variant: [1, "variant"], size: [1, "size"], extended: [1, "extended"], disabled: [1, "disabled"], type: [1, "type"], ariaLabel: [1, "ariaLabel"] }, ngContentSelectors: _c0$C, decls: 2, vars: 7, consts: [[1, "kpt-fab", 3, "type", "disabled"]], template: function KptFab_Template(rf, ctx) { if (rf & 1) {
244
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptFab, selectors: [["kpt-fab"]], hostAttrs: [1, "kpt-fab-host"], inputs: { variant: [1, "variant"], size: [1, "size"], extended: [1, "extended"], disabled: [1, "disabled"], type: [1, "type"], ariaLabel: [1, "ariaLabel"] }, ngContentSelectors: _c0$D, decls: 2, vars: 7, consts: [[1, "kpt-fab", 3, "type", "disabled"]], template: function KptFab_Template(rf, ctx) { if (rf & 1) {
230
245
  i0.ɵɵprojectionDef();
231
246
  i0.ɵɵdomElementStart(0, "button", 0);
232
247
  i0.ɵɵprojection(1);
@@ -253,106 +268,6 @@ class KptFab {
253
268
  }], null, { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], extended: [{ type: i0.Input, args: [{ isSignal: true, alias: "extended", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] }); })();
254
269
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptFab, { className: "KptFab", filePath: "lib/fab/fab.component.ts", lineNumber: 28 }); })();
255
270
 
256
- const KPT_ICONS = {
257
- 'menu': '<path d="M4 6l16 0" /> <path d="M4 12l16 0" /> <path d="M4 18l16 0" />',
258
- 'x': '<path d="M18 6l-12 12" /> <path d="M6 6l12 12" />',
259
- 'chevron-up': '<path d="M6 15l6 -6l6 6" />',
260
- 'chevron-down': '<path d="M6 9l6 6l6 -6" />',
261
- 'chevron-left': '<path d="M15 6l-6 6l6 6" />',
262
- 'chevron-right': '<path d="M9 6l6 6l-6 6" />',
263
- 'check': '<path d="M5 12l5 5l10 -10" />',
264
- 'search': '<path d="M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" /> <path d="M21 21l-6 -6" />',
265
- 'grip-vertical': '<path d="M8 5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /> <path d="M8 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /> <path d="M8 19a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /> <path d="M14 5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /> <path d="M14 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /> <path d="M14 19a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />',
266
- 'info': '<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" /> <path d="M12 9h.01" /> <path d="M11 12h1v4h1" />',
267
- 'alert-triangle': '<path d="M12 9v4" /> <path d="M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0" /> <path d="M12 16h.01" />',
268
- 'circle-check': '<path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" /> <path d="M9 12l2 2l4 -4" />',
269
- 'circle-x': '<path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" /> <path d="M10 10l4 4m0 -4l-4 4" />',
270
- 'calendar': '<path d="M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12" /> <path d="M16 3v4" /> <path d="M8 3v4" /> <path d="M4 11h16" /> <path d="M11 15h1" /> <path d="M12 15v3" />',
271
- 'copy': '<path d="M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666" /> <path d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1" />',
272
- 'link': '<path d="M9 15l6 -6" /> <path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" /> <path d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" />',
273
- 'code': '<path d="M7 8l-4 4l4 4" /> <path d="M17 8l4 4l-4 4" /> <path d="M14 4l-4 16" />',
274
- 'bold': '<path d="M7 5h6a3.5 3.5 0 0 1 0 7h-6l0 -7" /> <path d="M13 12h1a3.5 3.5 0 0 1 0 7h-7v-7" />',
275
- 'italic': '<path d="M11 5l6 0" /> <path d="M7 19l6 0" /> <path d="M14 5l-4 14" />',
276
- 'underline': '<path d="M7 5v5a5 5 0 0 0 10 0v-5" /> <path d="M5 19h14" />',
277
- 'strikethrough': '<path d="M5 12l14 0" /> <path d="M16 6.5a4 2 0 0 0 -4 -1.5h-1a3.5 3.5 0 0 0 0 7h2a3.5 3.5 0 0 1 0 7h-1.5a4 2 0 0 1 -4 -1.5" />',
278
- 'list': '<path d="M9 6l11 0" /> <path d="M9 12l11 0" /> <path d="M9 18l11 0" /> <path d="M5 6l0 .01" /> <path d="M5 12l0 .01" /> <path d="M5 18l0 .01" />',
279
- 'list-numbers': '<path d="M11 6h9" /> <path d="M11 12h9" /> <path d="M12 18h8" /> <path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4" /> <path d="M6 10v-6l-2 2" />',
280
- 'indent-increase': '<path d="M20 6l-11 0" /> <path d="M20 12l-7 0" /> <path d="M20 18l-11 0" /> <path d="M4 8l4 4l-4 4" />',
281
- 'indent-decrease': '<path d="M20 6l-7 0" /> <path d="M20 12l-9 0" /> <path d="M20 18l-7 0" /> <path d="M8 8l-4 4l4 4" />',
282
- 'clear-formatting': '<path d="M17 15l4 4m0 -4l-4 4" /> <path d="M7 6v-1h11v1" /> <path d="M7 19l4 0" /> <path d="M13 5l-4 14" />',
283
- 'star': '<path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873l-6.158 -3.245" />',
284
- 'plus': '<path d="M12 5l0 14" /> <path d="M5 12l14 0" />',
285
- 'upload': '<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" /> <path d="M7 9l5 -5l5 5" /> <path d="M12 4l0 12" />',
286
- 'dots-vertical': '<path d="M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /> <path d="M11 19a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /> <path d="M11 5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />',
287
- 'photo': '<path d="M15 8h.01" /> <path d="M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12" /> <path d="M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5" /> <path d="M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3" />',
288
- 'trash': '<path d="M4 7l16 0" /> <path d="M10 11l0 6" /> <path d="M14 11l0 6" /> <path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" /> <path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />',
289
- 'pencil': '<path d="M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" /> <path d="M13.5 6.5l4 4" />',
290
- 'eye': '<path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /> <path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" />',
291
- 'eye-off': '<path d="M10.585 10.587a2 2 0 0 0 2.829 2.828" /> <path d="M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87" /> <path d="M3 3l18 18" />',
292
- 'minus': '<path d="M5 12l14 0" />',
293
- 'arrow-up': '<path d="M12 5l0 14" /> <path d="M18 11l-6 -6" /> <path d="M6 11l6 -6" />',
294
- 'arrow-down': '<path d="M12 5l0 14" /> <path d="M18 13l-6 6" /> <path d="M6 13l6 6" />',
295
- 'zoom-in': '<path d="M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" /> <path d="M7 10l6 0" /> <path d="M10 7l0 6" /> <path d="M21 21l-6 -6" />',
296
- 'info-circle': '<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" /> <path d="M12 9h.01" /> <path d="M11 12h1v4h1" />',
297
- 'phone': '<path d="M5 4h4l2 5l-2.5 1.5a11 11 0 0 0 5 5l1.5 -2.5l5 2v4a2 2 0 0 1 -2 2a16 16 0 0 1 -15 -15a2 2 0 0 1 2 -2" />',
298
- 'map-pin': '<path d="M9 11a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" /> <path d="M17.657 16.657l-4.243 4.243a2 2 0 0 1 -2.827 0l-4.244 -4.243a8 8 0 1 1 11.314 0z" />',
299
- 'world': '<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" /> <path d="M3.6 9h16.8" /> <path d="M3.6 15h16.8" /> <path d="M11.5 3a17 17 0 0 0 0 18" /> <path d="M12.5 3a17 17 0 0 1 0 18" />',
300
- 'clock': '<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" /> <path d="M12 7v5l3 3" />',
301
- 'align-left': '<path d="M4 6l16 0" /> <path d="M4 12l10 0" /> <path d="M4 18l14 0" />',
302
- 'align-center': '<path d="M4 6l16 0" /> <path d="M8 12l8 0" /> <path d="M6 18l12 0" />',
303
- 'align-right': '<path d="M4 6l16 0" /> <path d="M10 12l10 0" /> <path d="M6 18l14 0" />',
304
- 'align-justified': '<path d="M4 6l16 0" /> <path d="M4 12l16 0" /> <path d="M4 18l12 0" />',
305
- 'palette': '<path d="M12 21a9 9 0 0 1 0 -18a9 8 0 0 1 9 8a4.5 4 0 0 1 -4.5 4h-2.5a2 2 0 0 0 -1 3.75a1.3 1.3 0 0 1 -1 2.25" /> <path d="M8.5 10.5a1 1 0 1 0 2 0a1 1 0 0 0 -2 0" /> <path d="M12.5 7.5a1 1 0 1 0 2 0a1 1 0 0 0 -2 0" /> <path d="M16.5 10.5a1 1 0 1 0 2 0a1 1 0 0 0 -2 0" />',
306
- 'highlight': '<path d="M3 19h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" /> <path d="M12.5 5.5l4 4" /> <path d="M4.5 13.5l4 4" /> <path d="M21 15v4h-8" />',
307
- 'clipboard': '<path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" /> <path d="M9 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z" />',
308
- 'clipboard-text': '<path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" /> <path d="M9 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z" /> <path d="M9 12h6" /> <path d="M9 16h6" />',
309
- 'table': '<path d="M3 5a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-14z" /> <path d="M3 10h18" /> <path d="M10 3v18" />',
310
- 'mail': '<path d="M3 7a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-10z" /> <path d="M3 7l9 6l9 -6" />',
311
- 'share': '<path d="M6 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" /> <path d="M18 6m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" /> <path d="M18 18m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" /> <path d="M8.7 10.7l6.6 -3.4" /> <path d="M8.7 13.3l6.6 3.4" />',
312
- 'external-link': '<path d="M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6" /> <path d="M11 13l9 -9" /> <path d="M15 4h5v5" />',
313
- 'crosshair': '<path d="M4 12h4" /> <path d="M16 12h4" /> <path d="M12 4v4" /> <path d="M12 16v4" /> <path d="M12 12m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0" />',
314
- 'adjustments-horizontal': '<path d="M12 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /> <path d="M4 6l8 0" /> <path d="M16 6l4 0" /> <path d="M6 12a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /> <path d="M4 12l2 0" /> <path d="M10 12l10 0" /> <path d="M15 18a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /> <path d="M4 18l11 0" /> <path d="M19 18l1 0" />',
315
- };
316
-
317
- // Allowlist SVG dla treści przechodzącej przez `register()` — sam rejestr trafia bez sanitizera
318
- // wprost do `innerHTML` (`icon.component.ts`, markery mapy), więc runtime'owe wywołanie `register()`
319
- // z niezaufaną treścią (CMS/API/upload) byłoby DOM XSS. Wbudowany `KPT_ICONS` (build-time, zaufany)
320
- // nie przechodzi przez ten filtr. Zestaw tagów/atrybutów pokrywa 100% wbudowanych ikon i pełnego
321
- // zestawu Tabler (5130) — oba używają wyłącznie `<path d/fill/opacity/stroke>` — więc sanitizacja
322
- // jest dla nich no-opem.
323
- const ALLOWED_SVG_TAGS = new Set([
324
- 'path', 'circle', 'rect', 'g', 'line', 'polygon', 'polyline', 'ellipse',
325
- ]);
326
- const ALLOWED_SVG_ATTRS = new Set([
327
- 'd', 'cx', 'cy', 'r', 'rx', 'ry', 'x', 'y', 'x1', 'y1', 'x2', 'y2', 'width', 'height', 'points',
328
- 'fill', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin', 'opacity', 'transform',
329
- ]);
330
- /**
331
- * Sanityzuje fragment SVG do allowlisty tagów/atrybutów geometrii — patrz komentarz wyżej.
332
- *
333
- * Fragment MUSI być parsowany owinięty w `<svg>` — parser HTML przełącza się w tryb „foreign
334
- * content" dopiero po napotkaniu tagu `<svg>`, dopiero wtedy składnia samozamykająca (`<path .../>`)
335
- * jest respektowana. Bez wrappera `<path d="…" />` zostaje w zwykłym trybie HTML, gdzie `path` nie
336
- * jest elementem pustym — kolejne rodzeństwo trafiłoby jako jego DZIECKO zamiast obok niego.
337
- */
338
- function sanitizeSvgFragment(svg) {
339
- const tpl = document.createElement('template');
340
- tpl.innerHTML = `<svg>${svg}</svg>`;
341
- const root = tpl.content.firstElementChild;
342
- if (!root)
343
- return '';
344
- for (const el of Array.from(root.querySelectorAll('*'))) {
345
- if (!ALLOWED_SVG_TAGS.has(el.tagName.toLowerCase())) {
346
- el.remove();
347
- continue;
348
- }
349
- for (const attr of Array.from(el.attributes)) {
350
- if (!ALLOWED_SVG_ATTRS.has(attr.name.toLowerCase()))
351
- el.removeAttribute(attr.name);
352
- }
353
- }
354
- return root.innerHTML;
355
- }
356
271
  /**
357
272
  * Rejestr ikon dla `kpt-icon`. Zawiera wbudowany zestaw (używany przez komponenty).
358
273
  * Aby dodać pełny zestaw Tabler (5130 ikon), użyj `provideKptTablerIcons()`
@@ -394,21 +309,6 @@ class KptIconRegistry {
394
309
  type: Injectable,
395
310
  args: [{ providedIn: 'root' }]
396
311
  }], null, null); })();
397
- /**
398
- * Składa pełny znacznik `<svg>` z wewnętrznego SVG z rejestru.
399
- *
400
- * Wydzielone z `kpt-icon`, bo tego samego stringa potrzebują znaczniki mapy —
401
- * ich HTML powstaje poza Angularem, w DOM zarządzanym przez silnik mapy.
402
- * Pusty `inner` daje pusty string, żeby wołający nie musiał tego sprawdzać.
403
- */
404
- function renderKptIconSvg(inner, cssClass = 'kpt-icon') {
405
- if (!inner)
406
- return '';
407
- return (`<svg class="${cssClass}" viewBox="0 0 24 24" fill="none" stroke="currentColor"` +
408
- ' stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
409
- inner +
410
- '</svg>');
411
- }
412
312
 
413
313
  /**
414
314
  * Ikona Koncept UI (inline SVG, zestaw Tabler Icons — MIT). Rozmiar dziedziczy z `font-size`
@@ -539,7 +439,7 @@ class KptAvatar {
539
439
  }], null, { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }] }); })();
540
440
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptAvatar, { className: "KptAvatar", filePath: "lib/avatar/avatar.component.ts", lineNumber: 46 }); })();
541
441
 
542
- const _c0$B = ["*"];
442
+ const _c0$C = ["*"];
543
443
  /**
544
444
  * Znacznik (badge) — licznik lub kropka statusu. Standalone lub nałożony na treść (`overlay`).
545
445
  *
@@ -571,7 +471,7 @@ class KptBadge {
571
471
  ...(ngDevMode ? [{ debugName: "display" }] : /* istanbul ignore next */ []));
572
472
  }
573
473
  static { this.ɵfac = function KptBadge_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptBadge)(); }; }
574
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptBadge, selectors: [["kpt-badge"]], hostAttrs: [1, "kpt-badge-host"], inputs: { value: [1, "value"], variant: [1, "variant"], size: [1, "size"], dot: [1, "dot"], overlay: [1, "overlay"], max: [1, "max"] }, ngContentSelectors: _c0$B, decls: 3, vars: 7, consts: [[1, "kpt-badge"]], template: function KptBadge_Template(rf, ctx) { if (rf & 1) {
474
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptBadge, selectors: [["kpt-badge"]], hostAttrs: [1, "kpt-badge-host"], inputs: { value: [1, "value"], variant: [1, "variant"], size: [1, "size"], dot: [1, "dot"], overlay: [1, "overlay"], max: [1, "max"] }, ngContentSelectors: _c0$C, decls: 3, vars: 7, consts: [[1, "kpt-badge"]], template: function KptBadge_Template(rf, ctx) { if (rf & 1) {
575
475
  i0.ɵɵprojectionDef();
576
476
  i0.ɵɵprojection(0);
577
477
  i0.ɵɵdomElementStart(1, "span", 0);
@@ -603,648 +503,6 @@ class KptBadge {
603
503
  /** Token konfiguracji i18n. Konsumowany przez `KptI18n`. */
604
504
  const KPT_I18N_CONFIG = new InjectionToken('KPT_I18N_CONFIG');
605
505
 
606
- /*
607
- * Kontrakt tłumaczeń Koncept UI + słowniki bazowe (EN, PL).
608
- *
609
- * Plik jest celowo wolny od zależności Angulara — to czysty TypeScript/JSON.
610
- * Dzięki temu ten sam kontrakt (`KptMessages`) i te same słowniki przenoszą się
611
- * 1:1 do przyszłego portu React (Context + hook zamiast DI).
612
- *
613
- * Autor nowego języka wypełnia strukturę `KptMessages` (np. `de.json`) i podaje
614
- * ją przez `provideKptI18n({ locale: 'de', messages: { de } })`. Brakujące klucze
615
- * spadają na fallback EN.
616
- */
617
- const KPT_MESSAGES_EN = {
618
- common: {
619
- close: 'Close',
620
- remove: 'Remove',
621
- previous: 'Previous',
622
- next: 'Next',
623
- clear: 'Clear',
624
- done: 'Done',
625
- all: 'All',
626
- },
627
- paginator: {
628
- rowsPerPage: 'Rows:',
629
- range: '{start}–{end} of {total}',
630
- prevPage: 'Previous page',
631
- nextPage: 'Next page',
632
- },
633
- select: {
634
- search: 'Search…',
635
- noResults: 'No results',
636
- removeChip: 'Remove',
637
- },
638
- listbox: {
639
- search: 'Search…',
640
- empty: 'No items',
641
- },
642
- dataView: {
643
- list: 'List',
644
- grid: 'Grid',
645
- empty: 'No items',
646
- count: '{count} items',
647
- },
648
- roadmap: {
649
- empty: 'No items on the roadmap',
650
- week: 'W',
651
- today: 'Today',
652
- milestone: 'Milestone',
653
- expandGroup: 'Expand group',
654
- collapseGroup: 'Collapse group',
655
- },
656
- map: {
657
- addLocation: 'Add location',
658
- chooseCategory: 'Choose a category',
659
- myLocation: 'My location',
660
- locateMe: 'Centre on my location',
661
- locationDenied: 'Location access denied',
662
- locationUnavailable: 'Location unavailable',
663
- zoomIn: 'Zoom in',
664
- zoomOut: 'Zoom out',
665
- legend: 'Legend',
666
- showCategory: 'Show {category}',
667
- hideCategory: 'Hide {category}',
668
- cluster: 'Group of {count} locations',
669
- clusterItems: 'Locations in this group',
670
- fieldRequired: '{label} is required',
671
- lookingUpAddress: 'Looking up the address…',
672
- addressNotFound: 'No address found for this point',
673
- latitude: 'Latitude',
674
- longitude: 'Longitude',
675
- empty: 'No locations',
676
- save: 'Save',
677
- cancel: 'Cancel',
678
- poi: {
679
- distanceAway: '{distance} away',
680
- openNow: 'Open',
681
- closedNow: 'Closed',
682
- opensAt: 'opens at {time}',
683
- closesAt: 'closes at {time}',
684
- alwaysOpen: 'Open 24/7',
685
- openingHours: 'Opening hours',
686
- closedDay: 'Closed',
687
- call: 'Call',
688
- sendEmail: 'Send an e-mail',
689
- openWebsite: 'Open the website',
690
- coordinates: 'Coordinates',
691
- copy: 'Copy',
692
- copied: 'Copied',
693
- share: 'Share',
694
- addFavourite: 'Add to favourites',
695
- removeFavourite: 'Remove from favourites',
696
- noPhoto: 'No photo',
697
- },
698
- search: {
699
- placeholder: 'Search for an address…',
700
- label: 'Search for an address',
701
- results: 'Address suggestions',
702
- clear: 'Clear the search',
703
- noResults: 'No matching places',
704
- minLength: 'Type at least {count} characters',
705
- searching: 'Searching…',
706
- found: '{count} suggestions',
707
- },
708
- field: {
709
- invalidEmail: 'Enter a valid e-mail address',
710
- invalidUrl: 'Enter an address starting with http:// or https://',
711
- imageTooLarge: 'The picture must be no larger than {max}',
712
- pickImage: 'Pick a picture',
713
- orPasteUrl: 'or paste a picture address',
714
- removeImage: 'Remove the picture',
715
- imagePreview: 'Picture preview',
716
- hoursClosed: 'Closed',
717
- hoursFrom: 'From',
718
- hoursTo: 'To',
719
- hoursSameAllWeek: 'Same all week',
720
- hoursAddRange: 'Add a second range',
721
- hoursRemoveRange: 'Remove the range',
722
- hoursIncomplete: 'Set both times for {day} or mark the day as closed',
723
- },
724
- },
725
- dataTable: {
726
- search: 'Search…',
727
- exportCsv: 'Export CSV',
728
- loading: 'Loading…',
729
- empty: 'No data',
730
- selectAll: 'Select all',
731
- selectRow: 'Select row',
732
- expandRow: 'Expand row',
733
- filter: 'Filter: {column}',
734
- filterMin: 'Filter min: {column}',
735
- filterMax: 'Filter max: {column}',
736
- all: 'All',
737
- dateRange: 'Date range',
738
- min: 'min',
739
- max: 'max',
740
- editCell: 'Edit: {column}',
741
- total: 'Total',
742
- },
743
- confirm: {
744
- header: 'Confirmation',
745
- accept: 'Confirm',
746
- reject: 'Cancel',
747
- },
748
- fileUpload: {
749
- hint: '<strong>Click</strong> or drag files here',
750
- remove: 'Remove',
751
- },
752
- chipsInput: {
753
- placeholder: 'Add and press Enter…',
754
- },
755
- dateRange: {
756
- placeholder: 'Select range',
757
- from: 'From',
758
- to: 'To',
759
- fromTime: 'From (time)',
760
- toTime: 'To (time)',
761
- },
762
- datepicker: {
763
- prevMonth: 'Previous month',
764
- nextMonth: 'Next month',
765
- prevYear: 'Previous year',
766
- nextYear: 'Next year',
767
- prevYears: 'Previous years',
768
- nextYears: 'Next years',
769
- prevDecades: 'Previous decades',
770
- nextDecades: 'Next decades',
771
- chooseMonth: 'Choose month',
772
- chooseYear: 'Choose year',
773
- chooseDecade: 'Choose decade',
774
- calendar: 'Calendar',
775
- month: 'Month',
776
- time: 'Time',
777
- },
778
- pickList: {
779
- available: 'Available',
780
- selected: 'Selected',
781
- moveAllRight: 'Move all right',
782
- moveRight: 'Move right',
783
- moveLeft: 'Move left',
784
- moveAllLeft: 'Move all left',
785
- },
786
- orderList: {
787
- up: 'Up',
788
- down: 'Down',
789
- },
790
- inputNumber: {
791
- decrement: 'Decrease',
792
- increment: 'Increase',
793
- },
794
- password: {
795
- show: 'Show password',
796
- hide: 'Hide password',
797
- strength: ['Very weak', 'Weak', 'Medium', 'Good', 'Strong'],
798
- },
799
- spinner: {
800
- label: 'Loading',
801
- },
802
- speedDial: {
803
- actions: 'Actions',
804
- },
805
- scrollTop: {
806
- label: 'Scroll to top',
807
- },
808
- splitButton: {
809
- more: 'More actions',
810
- },
811
- panel: {
812
- toggle: 'Collapse / expand',
813
- },
814
- appShell: {
815
- toggleNavigation: 'Toggle navigation',
816
- navigation: 'Main navigation',
817
- },
818
- breadcrumb: {
819
- label: 'breadcrumb',
820
- },
821
- galleria: {
822
- image: 'Image {index}',
823
- },
824
- carousel: {
825
- slide: 'Slide {index}',
826
- },
827
- richText: {
828
- copy: 'Copy',
829
- paste: 'Paste with formatting',
830
- pasteText: 'Paste without formatting',
831
- heading: 'Style',
832
- bold: 'Bold',
833
- italic: 'Italic',
834
- underline: 'Underline',
835
- strike: 'Strikethrough',
836
- ul: 'Bulleted list',
837
- ol: 'Numbered list',
838
- indent: 'Increase indent',
839
- outdent: 'Decrease indent',
840
- foreColor: 'Text color',
841
- backColor: 'Text background color',
842
- alignLeft: 'Align left',
843
- alignCenter: 'Center',
844
- alignRight: 'Align right',
845
- alignJustify: 'Justify',
846
- link: 'Insert link',
847
- table: 'Table',
848
- clear: 'Clear formatting',
849
- html: 'HTML preview',
850
- styleNormal: 'Normal',
851
- styleHeading: 'Heading {level}',
852
- linkPrompt: 'URL:',
853
- htmlSource: 'HTML source',
854
- paletteCustom: 'Custom…',
855
- menu: {
856
- column: 'Column',
857
- row: 'Row',
858
- cell: 'Cell',
859
- insertLeft: 'Insert left',
860
- insertRight: 'Insert right',
861
- headerColumn: 'Header column',
862
- deleteColumn: 'Delete column',
863
- insertAbove: 'Insert above',
864
- insertBelow: 'Insert below',
865
- headerRow: 'Header row',
866
- deleteRow: 'Delete row',
867
- cellBackground: 'Background color',
868
- alignLeft: 'Left',
869
- alignCenter: 'Center',
870
- alignRight: 'Right',
871
- mergeCells: 'Merge cells',
872
- splitCell: 'Split cell',
873
- border: 'Border…',
874
- deleteTable: 'Delete table',
875
- },
876
- border: {
877
- table: 'Table',
878
- cell: 'Cell',
879
- none: 'None',
880
- thin: 'Thin',
881
- medium: 'Medium',
882
- thick: 'Thick',
883
- customColor: 'Color…',
884
- },
885
- },
886
- auth: {
887
- signInTitle: 'Sign in',
888
- signInSubtitle: 'Use your e-mail and password.',
889
- signUpTitle: 'Create account',
890
- signUpSubtitle: 'It takes less than a minute.',
891
- forgotTitle: 'Reset password',
892
- forgotSubtitle: 'We will send a reset link to your e-mail.',
893
- name: 'Full name',
894
- email: 'E-mail',
895
- emailPlaceholder: 'you@company.com',
896
- password: 'Password',
897
- passwordHint: 'At least {min} characters.',
898
- confirmPassword: 'Repeat password',
899
- remember: 'Remember me',
900
- terms: 'I accept the terms of service',
901
- forgotLink: 'Forgot password?',
902
- backToSignIn: 'Back to sign in',
903
- signInSubmit: 'Sign in',
904
- signUpSubmit: 'Create account',
905
- resetSubmit: 'Send reset link',
906
- orContinueWith: 'or continue with',
907
- continueWith: 'Continue with {provider}',
908
- noAccount: 'No account yet?',
909
- haveAccount: 'Already have an account?',
910
- signInSwitch: 'Sign in',
911
- signUpSwitch: 'Sign up',
912
- errorRequired: 'This field is required',
913
- errorEmail: 'Enter a valid e-mail address',
914
- errorMinLength: 'Use at least {min} characters',
915
- errorMismatch: 'Passwords do not match',
916
- errorInvalid: 'Invalid value',
917
- promo: {
918
- signInTitle: 'Welcome back',
919
- signInText: 'Sign in to pick up where you left off.',
920
- signUpTitle: 'New here?',
921
- signUpText: 'Create an account and start in a minute.',
922
- },
923
- },
924
- };
925
- const KPT_MESSAGES_PL = {
926
- common: {
927
- close: 'Zamknij',
928
- remove: 'Usuń',
929
- previous: 'Poprzedni',
930
- next: 'Następny',
931
- clear: 'Wyczyść',
932
- done: 'Gotowe',
933
- all: 'Wszystkie',
934
- },
935
- paginator: {
936
- rowsPerPage: 'Wierszy:',
937
- range: '{start}–{end} z {total}',
938
- prevPage: 'Poprzednia strona',
939
- nextPage: 'Następna strona',
940
- },
941
- select: {
942
- search: 'Szukaj…',
943
- noResults: 'Brak wyników',
944
- removeChip: 'Usuń',
945
- },
946
- listbox: {
947
- search: 'Szukaj…',
948
- empty: 'Brak pozycji',
949
- },
950
- dataView: {
951
- list: 'Lista',
952
- grid: 'Siatka',
953
- empty: 'Brak elementów',
954
- count: '{count} elementów',
955
- },
956
- roadmap: {
957
- empty: 'Brak elementów na roadmapie',
958
- week: 'T',
959
- today: 'Dziś',
960
- milestone: 'Kamień milowy',
961
- expandGroup: 'Rozwiń grupę',
962
- collapseGroup: 'Zwiń grupę',
963
- },
964
- map: {
965
- addLocation: 'Dodaj lokalizację',
966
- chooseCategory: 'Wybierz kategorię',
967
- myLocation: 'Moje położenie',
968
- locateMe: 'Wyśrodkuj na moim położeniu',
969
- locationDenied: 'Brak zgody na dostęp do lokalizacji',
970
- locationUnavailable: 'Położenie niedostępne',
971
- zoomIn: 'Przybliż',
972
- zoomOut: 'Oddal',
973
- legend: 'Legenda',
974
- showCategory: 'Pokaż: {category}',
975
- hideCategory: 'Ukryj: {category}',
976
- cluster: 'Grupa {count} lokalizacji',
977
- clusterItems: 'Lokalizacje w tej grupie',
978
- fieldRequired: 'Pole „{label}" jest wymagane',
979
- lookingUpAddress: 'Szukam adresu…',
980
- addressNotFound: 'Nie znaleziono adresu dla tego punktu',
981
- latitude: 'Szerokość',
982
- longitude: 'Długość',
983
- empty: 'Brak lokalizacji',
984
- save: 'Zapisz',
985
- cancel: 'Anuluj',
986
- poi: {
987
- distanceAway: '{distance} od Ciebie',
988
- openNow: 'Otwarte',
989
- closedNow: 'Zamknięte',
990
- opensAt: 'otwarcie o {time}',
991
- closesAt: 'zamknięcie o {time}',
992
- alwaysOpen: 'Czynne całą dobę',
993
- openingHours: 'Godziny otwarcia',
994
- closedDay: 'Zamknięte',
995
- call: 'Zadzwoń',
996
- sendEmail: 'Napisz wiadomość',
997
- openWebsite: 'Otwórz stronę',
998
- coordinates: 'Współrzędne',
999
- copy: 'Kopiuj',
1000
- copied: 'Skopiowano',
1001
- share: 'Udostępnij',
1002
- addFavourite: 'Dodaj do ulubionych',
1003
- removeFavourite: 'Usuń z ulubionych',
1004
- noPhoto: 'Brak zdjęcia',
1005
- },
1006
- search: {
1007
- placeholder: 'Szukaj adresu…',
1008
- label: 'Szukaj adresu',
1009
- results: 'Podpowiedzi adresów',
1010
- clear: 'Wyczyść wyszukiwanie',
1011
- noResults: 'Brak pasujących miejsc',
1012
- minLength: 'Wpisz więcej znaków (minimum: {count})',
1013
- searching: 'Szukam…',
1014
- found: 'Podpowiedzi: {count}',
1015
- },
1016
- field: {
1017
- invalidEmail: 'Podaj poprawny adres e-mail',
1018
- invalidUrl: 'Podaj adres zaczynający się od http:// albo https://',
1019
- imageTooLarge: 'Zdjęcie może mieć najwyżej {max}',
1020
- pickImage: 'Wybierz zdjęcie',
1021
- orPasteUrl: 'albo wklej adres zdjęcia',
1022
- removeImage: 'Usuń zdjęcie',
1023
- imagePreview: 'Podgląd zdjęcia',
1024
- hoursClosed: 'Zamknięte',
1025
- hoursFrom: 'Od',
1026
- hoursTo: 'Do',
1027
- hoursSameAllWeek: 'Tak samo przez cały tydzień',
1028
- hoursAddRange: 'Dodaj drugi przedział',
1029
- hoursRemoveRange: 'Usuń przedział',
1030
- hoursIncomplete: 'Podaj obie godziny dla dnia {day} albo oznacz go jako zamknięty',
1031
- },
1032
- },
1033
- dataTable: {
1034
- search: 'Szukaj…',
1035
- exportCsv: 'Eksport CSV',
1036
- loading: 'Ładowanie…',
1037
- empty: 'Brak danych',
1038
- selectAll: 'Zaznacz wszystkie',
1039
- selectRow: 'Zaznacz wiersz',
1040
- expandRow: 'Rozwiń wiersz',
1041
- filter: 'Filtr: {column}',
1042
- filterMin: 'Filtr min: {column}',
1043
- filterMax: 'Filtr max: {column}',
1044
- all: 'Wszystkie',
1045
- dateRange: 'Zakres dat',
1046
- min: 'min',
1047
- max: 'max',
1048
- editCell: 'Edytuj: {column}',
1049
- total: 'Razem',
1050
- },
1051
- confirm: {
1052
- header: 'Potwierdzenie',
1053
- accept: 'Potwierdź',
1054
- reject: 'Anuluj',
1055
- },
1056
- fileUpload: {
1057
- hint: '<strong>Kliknij</strong> lub przeciągnij pliki tutaj',
1058
- remove: 'Usuń',
1059
- },
1060
- chipsInput: {
1061
- placeholder: 'Dodaj i naciśnij Enter…',
1062
- },
1063
- dateRange: {
1064
- placeholder: 'Wybierz zakres',
1065
- from: 'Od',
1066
- to: 'Koniec',
1067
- fromTime: 'Od (godzina)',
1068
- toTime: 'Koniec (godzina)',
1069
- },
1070
- datepicker: {
1071
- prevMonth: 'Poprzedni miesiąc',
1072
- nextMonth: 'Następny miesiąc',
1073
- prevYear: 'Poprzedni rok',
1074
- nextYear: 'Następny rok',
1075
- prevYears: 'Poprzednie lata',
1076
- nextYears: 'Następne lata',
1077
- prevDecades: 'Poprzednie dekady',
1078
- nextDecades: 'Następne dekady',
1079
- chooseMonth: 'Wybierz miesiąc',
1080
- chooseYear: 'Wybierz rok',
1081
- chooseDecade: 'Wybierz dekadę',
1082
- calendar: 'Kalendarz',
1083
- month: 'Miesiąc',
1084
- time: 'Godzina',
1085
- },
1086
- pickList: {
1087
- available: 'Dostępne',
1088
- selected: 'Wybrane',
1089
- moveAllRight: 'Przenieś wszystko w prawo',
1090
- moveRight: 'Przenieś w prawo',
1091
- moveLeft: 'Przenieś w lewo',
1092
- moveAllLeft: 'Przenieś wszystko w lewo',
1093
- },
1094
- orderList: {
1095
- up: 'W górę',
1096
- down: 'W dół',
1097
- },
1098
- inputNumber: {
1099
- decrement: 'Zmniejsz',
1100
- increment: 'Zwiększ',
1101
- },
1102
- password: {
1103
- show: 'Pokaż hasło',
1104
- hide: 'Ukryj hasło',
1105
- strength: ['Bardzo słabe', 'Słabe', 'Średnie', 'Dobre', 'Silne'],
1106
- },
1107
- spinner: {
1108
- label: 'Ładowanie',
1109
- },
1110
- speedDial: {
1111
- actions: 'Akcje',
1112
- },
1113
- scrollTop: {
1114
- label: 'Przewiń do góry',
1115
- },
1116
- splitButton: {
1117
- more: 'Więcej akcji',
1118
- },
1119
- panel: {
1120
- toggle: 'Zwiń / rozwiń',
1121
- },
1122
- appShell: {
1123
- toggleNavigation: 'Przełącz nawigację',
1124
- navigation: 'Nawigacja główna',
1125
- },
1126
- breadcrumb: {
1127
- label: 'breadcrumb',
1128
- },
1129
- galleria: {
1130
- image: 'Obraz {index}',
1131
- },
1132
- carousel: {
1133
- slide: 'Slajd {index}',
1134
- },
1135
- richText: {
1136
- copy: 'Kopiuj',
1137
- paste: 'Wklej z formatowaniem',
1138
- pasteText: 'Wklej bez formatowania',
1139
- heading: 'Styl',
1140
- bold: 'Pogrubienie',
1141
- italic: 'Kursywa',
1142
- underline: 'Podkreślenie',
1143
- strike: 'Przekreślenie',
1144
- ul: 'Lista punktowana',
1145
- ol: 'Lista numerowana',
1146
- indent: 'Dodaj wcięcie',
1147
- outdent: 'Usuń wcięcie',
1148
- foreColor: 'Kolor tekstu',
1149
- backColor: 'Kolor tła tekstu',
1150
- alignLeft: 'Wyrównaj do lewej',
1151
- alignCenter: 'Wyśrodkuj',
1152
- alignRight: 'Wyrównaj do prawej',
1153
- alignJustify: 'Wyjustuj',
1154
- link: 'Wstaw link',
1155
- table: 'Tabela',
1156
- clear: 'Usuń formatowanie',
1157
- html: 'Podgląd HTML',
1158
- styleNormal: 'Normalny',
1159
- styleHeading: 'Nagłówek {level}',
1160
- linkPrompt: 'Adres URL:',
1161
- htmlSource: 'Źródło HTML',
1162
- paletteCustom: 'Własny…',
1163
- menu: {
1164
- column: 'Kolumna',
1165
- row: 'Wiersz',
1166
- cell: 'Komórka',
1167
- insertLeft: 'Wstaw z lewej',
1168
- insertRight: 'Wstaw z prawej',
1169
- headerColumn: 'Nagłówek kolumny',
1170
- deleteColumn: 'Usuń kolumnę',
1171
- insertAbove: 'Wstaw powyżej',
1172
- insertBelow: 'Wstaw poniżej',
1173
- headerRow: 'Nagłówek wiersza',
1174
- deleteRow: 'Usuń wiersz',
1175
- cellBackground: 'Kolor tła',
1176
- alignLeft: 'Do lewej',
1177
- alignCenter: 'Wyśrodkuj',
1178
- alignRight: 'Do prawej',
1179
- mergeCells: 'Scal komórki',
1180
- splitCell: 'Podziel komórkę',
1181
- border: 'Obramowanie…',
1182
- deleteTable: 'Usuń tabelę',
1183
- },
1184
- border: {
1185
- table: 'Tabela',
1186
- cell: 'Komórka',
1187
- none: 'Bez',
1188
- thin: 'Cienkie',
1189
- medium: 'Średnie',
1190
- thick: 'Grube',
1191
- customColor: 'Kolor…',
1192
- },
1193
- },
1194
- auth: {
1195
- signInTitle: 'Zaloguj się',
1196
- signInSubtitle: 'Użyj adresu e-mail i hasła.',
1197
- signUpTitle: 'Załóż konto',
1198
- signUpSubtitle: 'Zajmie mniej niż minutę.',
1199
- forgotTitle: 'Zresetuj hasło',
1200
- forgotSubtitle: 'Wyślemy link do zmiany hasła na podany adres.',
1201
- name: 'Imię i nazwisko',
1202
- email: 'E-mail',
1203
- emailPlaceholder: 'jan@firma.pl',
1204
- password: 'Hasło',
1205
- passwordHint: 'Co najmniej {min} znaków.',
1206
- confirmPassword: 'Powtórz hasło',
1207
- remember: 'Zapamiętaj mnie',
1208
- terms: 'Akceptuję regulamin',
1209
- forgotLink: 'Nie pamiętasz hasła?',
1210
- backToSignIn: 'Wróć do logowania',
1211
- signInSubmit: 'Zaloguj się',
1212
- signUpSubmit: 'Załóż konto',
1213
- resetSubmit: 'Wyślij link',
1214
- orContinueWith: 'lub kontynuuj przez',
1215
- continueWith: 'Kontynuuj przez {provider}',
1216
- noAccount: 'Nie masz jeszcze konta?',
1217
- haveAccount: 'Masz już konto?',
1218
- signInSwitch: 'Zaloguj się',
1219
- signUpSwitch: 'Załóż konto',
1220
- errorRequired: 'To pole jest wymagane',
1221
- errorEmail: 'Podaj poprawny adres e-mail',
1222
- errorMinLength: 'Użyj co najmniej {min} znaków',
1223
- errorMismatch: 'Hasła nie są takie same',
1224
- errorInvalid: 'Nieprawidłowa wartość',
1225
- promo: {
1226
- signInTitle: 'Witaj ponownie',
1227
- signInText: 'Zaloguj się, by wrócić do pracy.',
1228
- signUpTitle: 'Pierwszy raz u nas?',
1229
- signUpText: 'Załóż konto i zacznij w minutę.',
1230
- },
1231
- },
1232
- };
1233
-
1234
- /** Deep-merge `patch` na kopię `base` (łączy tylko obiekty, wartości nadpisuje). */
1235
- function deepMerge(base, patch) {
1236
- const out = { ...base };
1237
- for (const [key, value] of Object.entries(patch)) {
1238
- const current = out[key];
1239
- if (value && typeof value === 'object' && !Array.isArray(value) && current && typeof current === 'object') {
1240
- out[key] = deepMerge(current, value);
1241
- }
1242
- else if (value !== undefined) {
1243
- out[key] = value;
1244
- }
1245
- }
1246
- return out;
1247
- }
1248
506
  /**
1249
507
  * Serwis tłumaczeń Koncept UI. Trzyma rejestr słowników per język, bieżący locale
1250
508
  * (sygnał) i funkcję `t()` z interpolacją. Skonfiguruj przez `provideKptI18n(...)`.
@@ -1252,6 +510,9 @@ function deepMerge(base, patch) {
1252
510
  * Domyślnie EN. Języki bazowe: EN, PL. Dowolny inny język dodaje się jednym
1253
511
  * słownikiem (`registerMessages` lub `provideKptI18n({ messages: { de } })`);
1254
512
  * brakujące klucze spadają na EN.
513
+ *
514
+ * Rdzeń (`deepMerge`, `translate`) żyje w `@konce-pt/i18n` — ten sam, którego
515
+ * używa port React, więc oba frameworki tłumaczą identycznie.
1255
516
  */
1256
517
  class KptI18n {
1257
518
  constructor() {
@@ -1293,22 +554,7 @@ class KptI18n {
1293
554
  * interpolacją `{name}`. Brakujący klucz spada na EN, a w ostateczności zwraca sam klucz.
1294
555
  */
1295
556
  t(key, params) {
1296
- const raw = this.lookup(this.messages(), key) ?? this.lookup(KPT_MESSAGES_EN, key) ?? key;
1297
- if (!params)
1298
- return raw;
1299
- return raw.replace(/\{(\w+)\}/g, (_, name) => String(params[name] ?? `{${name}}`));
1300
- }
1301
- lookup(dict, key) {
1302
- let node = dict;
1303
- for (const part of key.split('.')) {
1304
- if (node && typeof node === 'object' && part in node) {
1305
- node = node[part];
1306
- }
1307
- else {
1308
- return undefined;
1309
- }
1310
- }
1311
- return typeof node === 'string' ? node : undefined;
557
+ return translate(this.messages(), key, params);
1312
558
  }
1313
559
  static { this.ɵfac = function KptI18n_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptI18n)(); }; }
1314
560
  static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: KptI18n, factory: KptI18n.ɵfac, providedIn: 'root' }); }
@@ -1318,7 +564,7 @@ class KptI18n {
1318
564
  args: [{ providedIn: 'root' }]
1319
565
  }], () => [], null); })();
1320
566
 
1321
- const _c0$A = ["*"];
567
+ const _c0$B = ["*"];
1322
568
  function KptSplitButton_ng_template_6_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
1323
569
  i0.ɵɵelement(0, "div", 7);
1324
570
  } }
@@ -1460,7 +706,7 @@ class KptSplitButton {
1460
706
  this.open.set(false);
1461
707
  }
1462
708
  static { this.ɵfac = function KptSplitButton_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptSplitButton)(); }; }
1463
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptSplitButton, selectors: [["kpt-split-button"]], hostAttrs: [1, "kpt-split-button-host"], inputs: { variant: [1, "variant"], items: [1, "items"], disabled: [1, "disabled"] }, outputs: { primaryClick: "primaryClick", selected: "selected" }, ngContentSelectors: _c0$A, decls: 7, vars: 8, consts: [["origin", "cdkOverlayOrigin"], [1, "kpt-split-button"], ["type", "button", 1, "kpt-split-button__main", 3, "click", "disabled"], ["type", "button", "cdkOverlayOrigin", "", 1, "kpt-split-button__toggle", 3, "click", "disabled"], ["name", "chevron-down"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayHasBackdrop"], ["role", "menu", 1, "kpt-split-button__panel"], ["role", "separator", 1, "kpt-split-button__separator"], ["role", "presentation", 1, "kpt-split-button__header"], ["type", "button", 1, "kpt-split-button__item", 3, "kpt-split-button__item--danger", "disabled"], ["size", "sm", 3, "src", "name", "icon"], [3, "name"], [1, "kpt-split-button__text"], [1, "kpt-split-button__label"], [1, "kpt-split-button__description"], ["type", "button", 1, "kpt-split-button__item", 3, "click", "disabled"], [1, "kpt-split-button__badge", 3, "value", "variant"]], template: function KptSplitButton_Template(rf, ctx) { if (rf & 1) {
709
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptSplitButton, selectors: [["kpt-split-button"]], hostAttrs: [1, "kpt-split-button-host"], inputs: { variant: [1, "variant"], items: [1, "items"], disabled: [1, "disabled"] }, outputs: { primaryClick: "primaryClick", selected: "selected" }, ngContentSelectors: _c0$B, decls: 7, vars: 8, consts: [["origin", "cdkOverlayOrigin"], [1, "kpt-split-button"], ["type", "button", 1, "kpt-split-button__main", 3, "click", "disabled"], ["type", "button", "cdkOverlayOrigin", "", 1, "kpt-split-button__toggle", 3, "click", "disabled"], ["name", "chevron-down"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayHasBackdrop"], ["role", "menu", 1, "kpt-split-button__panel"], ["role", "separator", 1, "kpt-split-button__separator"], ["role", "presentation", 1, "kpt-split-button__header"], ["type", "button", 1, "kpt-split-button__item", 3, "kpt-split-button__item--danger", "disabled"], ["size", "sm", 3, "src", "name", "icon"], [3, "name"], [1, "kpt-split-button__text"], [1, "kpt-split-button__label"], [1, "kpt-split-button__description"], ["type", "button", 1, "kpt-split-button__item", 3, "click", "disabled"], [1, "kpt-split-button__badge", 3, "value", "variant"]], template: function KptSplitButton_Template(rf, ctx) { if (rf & 1) {
1464
710
  i0.ɵɵprojectionDef();
1465
711
  i0.ɵɵelementStart(0, "div", 1)(1, "button", 2);
1466
712
  i0.ɵɵlistener("click", function KptSplitButton_Template_button_click_1_listener() { return ctx.primaryClick.emit(); });
@@ -1658,7 +904,15 @@ function provideKptI18n(config = {}) {
1658
904
  return makeEnvironmentProviders([{ provide: KPT_I18N_CONFIG, useValue: config }]);
1659
905
  }
1660
906
 
1661
- const _c0$z = ["*"];
907
+ /*
908
+ * Re-eksport kontraktu tłumaczeń z `@konce-pt/i18n`.
909
+ *
910
+ * Słowniki i typy żyją w osobnym pakiecie pure-TS, żeby port React korzystał
911
+ * z tego samego źródła prawdy. Ten plik trzyma dotychczasową ścieżkę importu,
912
+ * dzięki czemu komponenty i `public-api.ts` nie musiały się zmieniać.
913
+ */
914
+
915
+ const _c0$A = ["*"];
1662
916
  function KptChip_Conditional_2_Template(rf, ctx) { if (rf & 1) {
1663
917
  const _r1 = i0.ɵɵgetCurrentView();
1664
918
  i0.ɵɵelementStart(0, "button", 2);
@@ -1687,7 +941,7 @@ class KptChip {
1687
941
  this.i18n = inject(KptI18n);
1688
942
  }
1689
943
  static { this.ɵfac = function KptChip_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptChip)(); }; }
1690
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptChip, selectors: [["kpt-chip"]], hostAttrs: [1, "kpt-chip-host"], inputs: { variant: [1, "variant"], removable: [1, "removable"], disabled: [1, "disabled"] }, outputs: { removed: "removed" }, ngContentSelectors: _c0$z, decls: 3, vars: 4, consts: [[1, "kpt-chip"], ["type", "button", 1, "kpt-chip__remove", 3, "disabled"], ["type", "button", 1, "kpt-chip__remove", 3, "click", "disabled"], ["name", "x"]], template: function KptChip_Template(rf, ctx) { if (rf & 1) {
944
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptChip, selectors: [["kpt-chip"]], hostAttrs: [1, "kpt-chip-host"], inputs: { variant: [1, "variant"], removable: [1, "removable"], disabled: [1, "disabled"] }, outputs: { removed: "removed" }, ngContentSelectors: _c0$A, decls: 3, vars: 4, consts: [[1, "kpt-chip"], ["type", "button", 1, "kpt-chip__remove", 3, "disabled"], ["type", "button", 1, "kpt-chip__remove", 3, "click", "disabled"], ["name", "x"]], template: function KptChip_Template(rf, ctx) { if (rf & 1) {
1691
945
  i0.ɵɵprojectionDef();
1692
946
  i0.ɵɵelementStart(0, "span", 0);
1693
947
  i0.ɵɵprojection(1);
@@ -1908,7 +1162,7 @@ class KptSkeleton {
1908
1162
  /** Token DI, przez który kontrolka zgłasza `kpt-form-field` swój stan wypełnienia. */
1909
1163
  const KPT_FORM_FIELD_CONTROL = new InjectionToken('KPT_FORM_FIELD_CONTROL');
1910
1164
 
1911
- const _c0$y = ["*"];
1165
+ const _c0$z = ["*"];
1912
1166
  function KptFormField_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
1913
1167
  i0.ɵɵdomElementStart(0, "span", 6);
1914
1168
  i0.ɵɵtext(1, "*");
@@ -2017,7 +1271,7 @@ class KptFormField {
2017
1271
  i0.ɵɵqueryAdvance();
2018
1272
  } }, hostAttrs: [1, "kpt-form-field-host"], hostBindings: function KptFormField_HostBindings(rf, ctx) { if (rf & 1) {
2019
1273
  i0.ɵɵlistener("input", function KptFormField_input_HostBindingHandler() { return ctx.updateFilled(); })("change", function KptFormField_change_HostBindingHandler() { return ctx.updateFilled(); });
2020
- } }, inputs: { label: [1, "label"], hint: [1, "hint"], error: [1, "error"], required: [1, "required"], controlId: [1, "controlId"], labelType: [1, "labelType"] }, ngContentSelectors: _c0$y, decls: 7, vars: 10, consts: [[1, "kpt-form-field"], [1, "kpt-form-field__box"], [1, "kpt-form-field__label"], [1, "kpt-form-field__control"], ["role", "alert", 1, "kpt-form-field__message", "kpt-form-field__message--error"], [1, "kpt-form-field__message", "kpt-form-field__message--hint"], ["aria-hidden", "true", 1, "kpt-form-field__required"]], template: function KptFormField_Template(rf, ctx) { if (rf & 1) {
1274
+ } }, inputs: { label: [1, "label"], hint: [1, "hint"], error: [1, "error"], required: [1, "required"], controlId: [1, "controlId"], labelType: [1, "labelType"] }, ngContentSelectors: _c0$z, decls: 7, vars: 10, consts: [[1, "kpt-form-field"], [1, "kpt-form-field__box"], [1, "kpt-form-field__label"], [1, "kpt-form-field__control"], ["role", "alert", 1, "kpt-form-field__message", "kpt-form-field__message--error"], [1, "kpt-form-field__message", "kpt-form-field__message--hint"], ["aria-hidden", "true", 1, "kpt-form-field__required"]], template: function KptFormField_Template(rf, ctx) { if (rf & 1) {
2021
1275
  i0.ɵɵprojectionDef();
2022
1276
  i0.ɵɵdomElementStart(0, "div", 0)(1, "div", 1);
2023
1277
  i0.ɵɵconditionalCreate(2, KptFormField_Conditional_2_Template, 3, 3, "label", 2);
@@ -2118,7 +1372,7 @@ class KptInput {
2118
1372
  }], null, { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }] }); })();
2119
1373
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptInput, { className: "KptInput", filePath: "lib/input/input.component.ts", lineNumber: 49 }); })();
2120
1374
 
2121
- const _c0$x = ["*"];
1375
+ const _c0$y = ["*"];
2122
1376
  function KptCheckbox_Conditional_5_Template(rf, ctx) { if (rf & 1) {
2123
1377
  i0.ɵɵdomElementStart(0, "span", 5);
2124
1378
  i0.ɵɵtext(1);
@@ -2149,7 +1403,7 @@ class KptCheckbox {
2149
1403
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2150
1404
  }
2151
1405
  static { this.ɵfac = function KptCheckbox_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptCheckbox)(); }; }
2152
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptCheckbox, selectors: [["kpt-checkbox"]], hostAttrs: [1, "kpt-checkbox-host"], inputs: { checked: [1, "checked"], disabled: [1, "disabled"], invalid: [1, "invalid"], touched: [1, "touched"], label: [1, "label"] }, outputs: { checked: "checkedChange", touch: "touch" }, ngContentSelectors: _c0$x, decls: 7, vars: 6, consts: [[1, "kpt-checkbox"], ["type", "checkbox", 1, "kpt-checkbox__input", 3, "change", "blur", "checked", "disabled"], ["aria-hidden", "true", 1, "kpt-checkbox__box"], ["viewBox", "0 0 16 16", 1, "kpt-checkbox__check"], ["d", "M13 4.5 6.5 11 3 7.5"], [1, "kpt-checkbox__label"]], template: function KptCheckbox_Template(rf, ctx) { if (rf & 1) {
1406
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptCheckbox, selectors: [["kpt-checkbox"]], hostAttrs: [1, "kpt-checkbox-host"], inputs: { checked: [1, "checked"], disabled: [1, "disabled"], invalid: [1, "invalid"], touched: [1, "touched"], label: [1, "label"] }, outputs: { checked: "checkedChange", touch: "touch" }, ngContentSelectors: _c0$y, decls: 7, vars: 6, consts: [[1, "kpt-checkbox"], ["type", "checkbox", 1, "kpt-checkbox__input", 3, "change", "blur", "checked", "disabled"], ["aria-hidden", "true", 1, "kpt-checkbox__box"], ["viewBox", "0 0 16 16", 1, "kpt-checkbox__check"], ["d", "M13 4.5 6.5 11 3 7.5"], [1, "kpt-checkbox__label"]], template: function KptCheckbox_Template(rf, ctx) { if (rf & 1) {
2153
1407
  i0.ɵɵprojectionDef();
2154
1408
  i0.ɵɵdomElementStart(0, "label", 0)(1, "input", 1);
2155
1409
  i0.ɵɵdomListener("change", function KptCheckbox_Template_input_change_1_listener($event) { return ctx.checked.set($event.target.checked); })("blur", function KptCheckbox_Template_input_blur_1_listener() { return ctx.touch.emit(); });
@@ -2196,7 +1450,7 @@ class KptCheckbox {
2196
1450
  }], null, { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] }); })();
2197
1451
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptCheckbox, { className: "KptCheckbox", filePath: "lib/checkbox/checkbox.component.ts", lineNumber: 44 }); })();
2198
1452
 
2199
- const _c0$w = ["*"];
1453
+ const _c0$x = ["*"];
2200
1454
  function KptSwitch_Conditional_1_Template(rf, ctx) { if (rf & 1) {
2201
1455
  i0.ɵɵdomElementStart(0, "span", 1);
2202
1456
  i0.ɵɵtext(1);
@@ -2262,7 +1516,7 @@ class KptSwitch {
2262
1516
  ...(ngDevMode ? [{ debugName: "stateLabel" }] : /* istanbul ignore next */ []));
2263
1517
  }
2264
1518
  static { this.ɵfac = function KptSwitch_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptSwitch)(); }; }
2265
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptSwitch, selectors: [["kpt-switch"]], hostAttrs: [1, "kpt-switch-host"], inputs: { checked: [1, "checked"], disabled: [1, "disabled"], invalid: [1, "invalid"], touched: [1, "touched"], label: [1, "label"], labelPosition: [1, "labelPosition"], onLabel: [1, "onLabel"], offLabel: [1, "offLabel"] }, outputs: { checked: "checkedChange", touch: "touch" }, ngContentSelectors: _c0$w, decls: 8, vars: 8, consts: [[1, "kpt-switch"], [1, "kpt-switch__label", "kpt-switch__label--start"], ["type", "checkbox", "role", "switch", 1, "kpt-switch__input", 3, "change", "blur", "checked", "disabled"], ["aria-hidden", "true", 1, "kpt-switch__track"], [1, "kpt-switch__thumb"], [1, "kpt-switch__label"], [1, "kpt-switch__state", 3, "kpt-switch__state--on"], [1, "kpt-switch__state"]], template: function KptSwitch_Template(rf, ctx) { if (rf & 1) {
1519
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptSwitch, selectors: [["kpt-switch"]], hostAttrs: [1, "kpt-switch-host"], inputs: { checked: [1, "checked"], disabled: [1, "disabled"], invalid: [1, "invalid"], touched: [1, "touched"], label: [1, "label"], labelPosition: [1, "labelPosition"], onLabel: [1, "onLabel"], offLabel: [1, "offLabel"] }, outputs: { checked: "checkedChange", touch: "touch" }, ngContentSelectors: _c0$x, decls: 8, vars: 8, consts: [[1, "kpt-switch"], [1, "kpt-switch__label", "kpt-switch__label--start"], ["type", "checkbox", "role", "switch", 1, "kpt-switch__input", 3, "change", "blur", "checked", "disabled"], ["aria-hidden", "true", 1, "kpt-switch__track"], [1, "kpt-switch__thumb"], [1, "kpt-switch__label"], [1, "kpt-switch__state", 3, "kpt-switch__state--on"], [1, "kpt-switch__state"]], template: function KptSwitch_Template(rf, ctx) { if (rf & 1) {
2266
1520
  i0.ɵɵprojectionDef();
2267
1521
  i0.ɵɵdomElementStart(0, "label", 0);
2268
1522
  i0.ɵɵconditionalCreate(1, KptSwitch_Conditional_1_Template, 2, 1, "span", 1);
@@ -2806,23 +2060,12 @@ class KptSelect {
2806
2060
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptSelect, { className: "KptSelect", filePath: "lib/select/select.component.ts", lineNumber: 42 }); })();
2807
2061
 
2808
2062
  /*
2809
- * Pomocniki nazw dni/miesięcy wyliczane z `Intl` — sterowane bieżącym locale i18n.
2810
- * Dzięki temu kalendarze (`kpt-datepicker`, `kpt-date-range`) nie trzymają
2811
- * zaszytych tablic nazw i działają dla dowolnego języka.
2063
+ * Re-eksport pomocników `Intl` z `@konce-pt/i18n` — nazwy dni i miesięcy
2064
+ * wyliczane z bieżącego locale. Ścieżka zachowana dla kalendarzy
2065
+ * (`kpt-datepicker`, `kpt-date-range`), które importują ją względnie.
2812
2066
  */
2813
- /** Krótkie nazwy dni tygodnia, zaczynając od poniedziałku (Pn…Nd). */
2814
- function weekdayNames(locale) {
2815
- const fmt = new Intl.DateTimeFormat(locale, { weekday: 'short' });
2816
- // 2024-01-01 (UTC) to poniedziałek.
2817
- return Array.from({ length: 7 }, (_, i) => fmt.format(new Date(Date.UTC(2024, 0, 1 + i))));
2818
- }
2819
- /** Pełne nazwy miesięcy (styczeń…grudzień / January…December). */
2820
- function monthNames(locale) {
2821
- const fmt = new Intl.DateTimeFormat(locale, { month: 'long' });
2822
- return Array.from({ length: 12 }, (_, i) => fmt.format(new Date(Date.UTC(2024, i, 1))));
2823
- }
2824
2067
 
2825
- const _forTrack0$a = ($index, $item) => $item.hour24;
2068
+ const _forTrack0$a = ($index, $item) => $item.value;
2826
2069
  function KptClock_Conditional_8_Template(rf, ctx) { if (rf & 1) {
2827
2070
  const _r2 = i0.ɵɵgetCurrentView();
2828
2071
  i0.ɵɵdomElementStart(0, "div", 5)(1, "button", 9);
@@ -2878,14 +2121,6 @@ function KptClock_Conditional_14_Template(rf, ctx) { if (rf & 1) {
2878
2121
  const ctx_r2 = i0.ɵɵnextContext();
2879
2122
  i0.ɵɵrepeater(ctx_r2.minuteMarks());
2880
2123
  } }
2881
- const R_OUTER = 40;
2882
- const R_INNER = 26;
2883
- const pad$2 = (n) => String(n).padStart(2, '0');
2884
- /** Pozycja znacznika (% tarczy) na pierścieniu o promieniu `radius`: 12 na górze, zegarowo. */
2885
- function markPos(index, radius) {
2886
- const theta = (index / 12) * 2 * Math.PI;
2887
- return { x: 50 + radius * Math.sin(theta), y: 50 - radius * Math.cos(theta) };
2888
- }
2889
2124
  /**
2890
2125
  * Tarcza zegara (wybór godziny) — dwa etapy: godziny → minuty, klik lub przeciąganie.
2891
2126
  * Format 12/24h (`hourFormat`); w 24h dodatkowy wewnętrzny pierścień 13–00, w 12h AM/PM.
@@ -2913,82 +2148,43 @@ class KptClock {
2913
2148
  return h === 0 ? 12 : h;
2914
2149
  }, /* @ts-ignore */
2915
2150
  ...(ngDevMode ? [{ debugName: "hour12" }] : /* istanbul ignore next */ []));
2916
- this.hourLabel = computed(() => this.hourFormat() === 12 ? String(this.hour12()) : pad$2(this.hour()), /* @ts-ignore */
2151
+ this.hourLabel = computed(() => this.hourFormat() === 12 ? String(this.hour12()) : pad(this.hour()), /* @ts-ignore */
2917
2152
  ...(ngDevMode ? [{ debugName: "hourLabel" }] : /* istanbul ignore next */ []));
2918
- this.minuteLabel = computed(() => pad$2(this.minute()), /* @ts-ignore */
2153
+ this.minuteLabel = computed(() => pad(this.minute()), /* @ts-ignore */
2919
2154
  ...(ngDevMode ? [{ debugName: "minuteLabel" }] : /* istanbul ignore next */ []));
2920
- /** W 12h jeden pierścień; w 24h zewnętrzny (12, 1–11) i wewnętrzny (00, 13–23). */
2921
- this.hourMarks = computed(() => this.hourFormat() === 12 ? this.marks12h() : [...this.marks24hOuter(), ...this.marks24hInner()], /* @ts-ignore */
2155
+ /** Znaczniki tarczy — jeden pierścień w 12h, dwa w 24h (patrz `@konce-pt/datetime`). */
2156
+ this.hourMarks = computed(() => hourMarks(this.hour(), this.hourFormat() === 12 ? 12 : 24), /* @ts-ignore */
2922
2157
  ...(ngDevMode ? [{ debugName: "hourMarks" }] : /* istanbul ignore next */ []));
2923
- this.minuteMarks = computed(() => {
2924
- const cur = this.minute();
2925
- return Array.from({ length: 12 }, (_, i) => {
2926
- const val = i * 5;
2927
- return { label: pad$2(val), hour24: val, ...markPos(i, R_OUTER), inner: false, selected: cur === val };
2928
- });
2929
- }, /* @ts-ignore */
2158
+ this.minuteMarks = computed(() => minuteMarks(this.minute()), /* @ts-ignore */
2930
2159
  ...(ngDevMode ? [{ debugName: "minuteMarks" }] : /* istanbul ignore next */ []));
2931
- this.handAngle = computed(() => this.clockPhase() === 'hours' ? (this.hour() % 12) * 30 : this.minute() * 6, /* @ts-ignore */
2160
+ this.handAngle = computed(() => handAngle(this.hour(), this.minute(), this.clockPhase()), /* @ts-ignore */
2932
2161
  ...(ngDevMode ? [{ debugName: "handAngle" }] : /* istanbul ignore next */ []));
2933
- this.handInner = computed(() => this.clockPhase() === 'hours' && this.hourFormat() === 24 && (this.hour() === 0 || this.hour() >= 13), /* @ts-ignore */
2162
+ this.handInner = computed(() => handIsInner(this.hour(), this.hourFormat() === 12 ? 12 : 24, this.clockPhase()), /* @ts-ignore */
2934
2163
  ...(ngDevMode ? [{ debugName: "handInner" }] : /* istanbul ignore next */ []));
2935
2164
  // Synchronizacja wartości zewnętrznej → stan tarczy (zapis idempotentny, bez pętli).
2936
2165
  effect(() => {
2937
- const t = this.parse(this.value());
2166
+ const t = parseTime(this.value());
2938
2167
  this.hour.set(t?.h ?? 0);
2939
2168
  this.minute.set(t?.m ?? 0);
2940
2169
  });
2941
2170
  }
2942
- parse(v) {
2943
- const m = /^(\d{2}):(\d{2})$/.exec(v ?? '');
2944
- return m ? { h: +m[1], m: +m[2] } : null;
2945
- }
2946
2171
  emit() {
2947
- this.value.set(`${pad$2(this.hour())}:${pad$2(this.minute())}`);
2948
- }
2949
- from12h(h12, ap) {
2950
- const base = h12 % 12; // 12 → 0
2951
- return ap === 'PM' ? base + 12 : base;
2952
- }
2953
- marks12h() {
2954
- const ap = this.ampm();
2955
- const cur = this.hour();
2956
- return Array.from({ length: 12 }, (_, i) => {
2957
- const h12 = i === 0 ? 12 : i;
2958
- // Wartość docelowa bierze bieżące AM/PM — tarcza pokazuje tylko jedną połowę doby.
2959
- const hour24 = this.from12h(h12, ap);
2960
- return { label: String(h12), hour24, ...markPos(i, R_OUTER), inner: false, selected: cur === hour24 };
2961
- });
2962
- }
2963
- marks24hOuter() {
2964
- const cur = this.hour();
2965
- return Array.from({ length: 12 }, (_, i) => {
2966
- const hour24 = i === 0 ? 12 : i;
2967
- return { label: String(hour24), hour24, ...markPos(i, R_OUTER), inner: false, selected: cur === hour24 };
2968
- });
2969
- }
2970
- marks24hInner() {
2971
- const cur = this.hour();
2972
- return Array.from({ length: 12 }, (_, i) => {
2973
- const hour24 = i === 0 ? 0 : i + 12;
2974
- // `pad` daje '00' dla północy; 13–23 są już dwucyfrowe.
2975
- return { label: pad$2(hour24), hour24, ...markPos(i, R_INNER), inner: true, selected: cur === hour24 };
2976
- });
2172
+ this.value.set(`${pad(this.hour())}:${pad(this.minute())}`);
2977
2173
  }
2978
2174
  setPhase(phase) {
2979
2175
  this.clockPhase.set(phase);
2980
2176
  }
2981
2177
  setAmpm(target) {
2982
- this.hour.set(this.from12h(this.hour12(), target));
2178
+ this.hour.set(from12h(this.hour12(), target));
2983
2179
  this.emit();
2984
2180
  }
2985
2181
  pickHour(mark) {
2986
- this.hour.set(mark.hour24);
2182
+ this.hour.set(mark.value);
2987
2183
  this.clockPhase.set('minutes');
2988
2184
  this.emit();
2989
2185
  }
2990
2186
  pickMinute(mark) {
2991
- this.minute.set(mark.hour24);
2187
+ this.minute.set(mark.value);
2992
2188
  this.emit();
2993
2189
  }
2994
2190
  onDialPointer(event, face) {
@@ -3003,32 +2199,14 @@ class KptClock {
3003
2199
  if (deg < 0)
3004
2200
  deg += 360;
3005
2201
  if (this.clockPhase() === 'hours') {
3006
- this.setHourFromAngle(deg, Math.hypot(dx, dy) / (rect.width / 2));
2202
+ const radiusRatio = Math.hypot(dx, dy) / (rect.width / 2);
2203
+ this.hour.set(hourFromAngle(deg, radiusRatio, this.hourFormat() === 12 ? 12 : 24, this.hour()));
3007
2204
  }
3008
2205
  else {
3009
- this.setMinuteFromAngle(deg);
2206
+ this.minute.set(minuteFromAngle(deg, this.minuteStep()));
3010
2207
  }
3011
2208
  this.emit();
3012
2209
  }
3013
- /** Godzina z kąta; w 24h o pierścieniu (a więc o 12–23 vs 0–11) decyduje promień kliknięcia. */
3014
- setHourFromAngle(deg, radius) {
3015
- const idx = Math.round(deg / 30) % 12;
3016
- if (this.hourFormat() === 12) {
3017
- this.hour.set(this.from12h(idx === 0 ? 12 : idx, this.ampm()));
3018
- return;
3019
- }
3020
- const inner = radius < (R_OUTER + R_INNER) / 2 / 50;
3021
- if (inner)
3022
- this.hour.set(idx === 0 ? 0 : idx + 12);
3023
- else
3024
- this.hour.set(idx === 0 ? 12 : idx);
3025
- }
3026
- /** Minuta z kąta, dociągnięta do `minuteStep`. */
3027
- setMinuteFromAngle(deg) {
3028
- const step = Math.max(1, this.minuteStep());
3029
- const raw = Math.round(deg / 6) % 60;
3030
- this.minute.set((Math.round(raw / step) * step) % 60);
3031
- }
3032
2210
  onDialUp() {
3033
2211
  if (this.clockPhase() === 'hours')
3034
2212
  this.clockPhase.set('minutes');
@@ -3101,7 +2279,7 @@ class KptClock {
3101
2279
  [style.transform]="'rotate(' + handAngle() + 'deg)'"
3102
2280
  ></span>
3103
2281
  @if (clockPhase() === 'hours') {
3104
- @for (mark of hourMarks(); track mark.hour24) {
2282
+ @for (mark of hourMarks(); track mark.value) {
3105
2283
  <button
3106
2284
  type="button"
3107
2285
  class="kpt-clock__num"
@@ -3113,7 +2291,7 @@ class KptClock {
3113
2291
  >{{ mark.label }}</button>
3114
2292
  }
3115
2293
  } @else {
3116
- @for (mark of minuteMarks(); track mark.hour24) {
2294
+ @for (mark of minuteMarks(); track mark.value) {
3117
2295
  <button
3118
2296
  type="button"
3119
2297
  class="kpt-clock__num"
@@ -3128,7 +2306,7 @@ class KptClock {
3128
2306
  </div>
3129
2307
  `, host: { class: 'kpt-clock-host' }, styles: ["@layer kpt.components{.kpt-clock-host{display:block}.kpt-clock__time{display:flex;align-items:center;justify-content:center;gap:var(--kpt-space-1, .25rem);margin-bottom:var(--kpt-space-3, .75rem);font-variant-numeric:tabular-nums}.kpt-clock__seg{border:0;background:none;padding:.1rem .4rem;border-radius:var(--kpt-radius-sm, .25rem);font-size:var(--kpt-font-size-2xl, 1.5rem);font-weight:var(--kpt-font-weight-semibold, 600);color:var(--kpt-color-on-surface-muted);cursor:pointer}.kpt-clock__seg.is-active{color:var(--kpt-color-primary);background:var(--kpt-color-muted)}.kpt-clock__colon{font-size:var(--kpt-font-size-2xl, 1.5rem);font-weight:var(--kpt-font-weight-semibold, 600);color:var(--kpt-color-on-surface-muted)}.kpt-clock__ampm{display:flex;flex-direction:column;gap:2px;margin-inline-start:var(--kpt-space-2, .5rem)}.kpt-clock__ampm button{border:var(--kpt-border-width-thin, 1px) solid var(--kpt-color-border);background:none;padding:.1rem .4rem;border-radius:var(--kpt-radius-sm, .25rem);font-size:var(--kpt-font-size-xs, .75rem);font-weight:var(--kpt-font-weight-semibold, 600);color:var(--kpt-color-on-surface-muted);cursor:pointer}.kpt-clock__ampm button.is-active{background:var(--kpt-color-primary);border-color:var(--kpt-color-primary);color:var(--kpt-color-on-primary)}.kpt-clock__face{position:relative;width:13rem;max-width:100%;aspect-ratio:1;margin:0 auto;border-radius:50%;background:var(--kpt-color-surface-variant);touch-action:none;-webkit-user-select:none;user-select:none}.kpt-clock__center{position:absolute;left:50%;top:50%;width:8px;height:8px;transform:translate(-50%,-50%);border-radius:50%;background:var(--kpt-color-primary);z-index:2}.kpt-clock__hand{position:absolute;left:50%;bottom:50%;width:2px;height:40%;margin-left:-1px;transform-origin:bottom center;background:var(--kpt-color-primary);z-index:1}.kpt-clock__hand--inner{height:26%}.kpt-clock__hand:before{content:\"\";position:absolute;top:-3px;left:50%;width:8px;height:8px;transform:translate(-50%);border-radius:50%;background:var(--kpt-color-primary)}.kpt-clock__num{position:absolute;transform:translate(-50%,-50%);display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:0;border-radius:50%;background:none;color:var(--kpt-color-on-surface);font:inherit;font-size:var(--kpt-font-size-sm, .875rem);cursor:pointer;z-index:2}.kpt-clock__num:hover{background:var(--kpt-color-muted)}.kpt-clock__num--inner{width:1.6rem;height:1.6rem;font-size:var(--kpt-font-size-xs, .75rem);color:var(--kpt-color-on-surface-muted)}.kpt-clock__num--selected{background:var(--kpt-color-primary)!important;color:var(--kpt-color-on-primary)}}\n"] }]
3130
2308
  }], () => [], { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], hourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourFormat", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }] }); })();
3131
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptClock, { className: "KptClock", filePath: "lib/datepicker/clock.component.ts", lineNumber: 100 }); })();
2309
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptClock, { className: "KptClock", filePath: "lib/datepicker/clock.component.ts", lineNumber: 93 }); })();
3132
2310
 
3133
2311
  const _forTrack0$9 = ($index, $item) => $item.iso;
3134
2312
  const _forTrack1$2 = ($index, $item) => $item.label;
@@ -3410,10 +2588,6 @@ function KptDatepicker_ng_template_7_Template(rf, ctx) { if (rf & 1) {
3410
2588
  i0.ɵɵadvance(2);
3411
2589
  i0.ɵɵconditional(ctx_r0.hasFooter() ? 3 : -1);
3412
2590
  } }
3413
- /** Kolejność poziomów panelu, od najdrobniejszego. Indeks = „wysokość" widoku. */
3414
- const LEVELS = ['day', 'month', 'year', 'decade'];
3415
- const pad$1 = (n) => String(n).padStart(2, '0');
3416
- const toIso$1 = (d) => `${d.getFullYear()}-${pad$1(d.getMonth() + 1)}-${pad$1(d.getDate())}`;
3417
2591
  /**
3418
2592
  * Wybór daty/godziny z własnym kalendarzem (CDK Overlay), Signal Forms.
3419
2593
  * Granulacja przez `selectionMode`: data, miesiąc+rok, rok, miesiąc, data+godzina, sama godzina.
@@ -3431,13 +2605,6 @@ const toIso$1 = (d) => `${d.getFullYear()}-${pad$1(d.getMonth() + 1)}-${pad$1(d.
3431
2605
  * <kpt-datepicker selectionMode="time" [(value)]="alarm" />
3432
2606
  */
3433
2607
  class KptDatepicker {
3434
- effectiveStartView() {
3435
- const commit = LEVELS.indexOf(this.commitLevel());
3436
- const top = LEVELS.indexOf(this.topLevel());
3437
- const wanted = this.startView();
3438
- const idx = wanted ? LEVELS.indexOf(wanted) : commit;
3439
- return LEVELS[Math.min(Math.max(idx, commit), top)];
3440
- }
3441
2608
  constructor() {
3442
2609
  this.value = model('', /* @ts-ignore */
3443
2610
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -3460,8 +2627,9 @@ class KptDatepicker {
3460
2627
  ...(ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []));
3461
2628
  /**
3462
2629
  * Poziom, od którego otwiera się panel. `null` = poziom zatwierdzania danego trybu
3463
- * (dni dla 'date'). Nie schodzi poniżej tego poziomu — `startView="day"` w trybie 'year'
3464
- * nie ma sensu i jest podnoszony do 'year'.
2630
+ * (dni dla 'date'). Przycięcie do zakresu trybu robi `resolveStartView` z `@konce-pt/datetime`:
2631
+ * `startView="day"` w trybie 'year' jest podnoszony do 'year', a tryb 'month' zostaje na swoim
2632
+ * poziomie, bo nie ma po czym nawigować.
3465
2633
  */
3466
2634
  this.startView = input(null, /* @ts-ignore */
3467
2635
  ...(ngDevMode ? [{ debugName: "startView" }] : /* istanbul ignore next */ []));
@@ -3509,21 +2677,8 @@ class KptDatepicker {
3509
2677
  this.panelView = signal('day', /* @ts-ignore */
3510
2678
  ...(ngDevMode ? [{ debugName: "panelView" }] : /* istanbul ignore next */ []));
3511
2679
  /** Poziom, na którym klik w komórkę zatwierdza wartość zamiast schodzić niżej. */
3512
- this.commitLevel = computed(() => {
3513
- switch (this.selectionMode()) {
3514
- case 'monthYear':
3515
- case 'month':
3516
- return 'month';
3517
- case 'year':
3518
- return 'year';
3519
- default:
3520
- return 'day';
3521
- }
3522
- }, /* @ts-ignore */
2680
+ this.commitLevel = computed(() => commitLevelFor(this.selectionMode()), /* @ts-ignore */
3523
2681
  ...(ngDevMode ? [{ debugName: "commitLevel" }] : /* istanbul ignore next */ []));
3524
- /** Tryb 'month' nie ma roku ani dekady — wartością jest samo 'MM'. */
3525
- this.topLevel = computed(() => this.selectionMode() === 'month' ? 'month' : 'decade', /* @ts-ignore */
3526
- ...(ngDevMode ? [{ debugName: "topLevel" }] : /* istanbul ignore next */ []));
3527
2682
  // ── Stan czasu (bufor 'HH:mm', 24h) ──
3528
2683
  this.timeStr = signal('', /* @ts-ignore */
3529
2684
  ...(ngDevMode ? [{ debugName: "timeStr" }] : /* istanbul ignore next */ []));
@@ -3544,15 +2699,9 @@ class KptDatepicker {
3544
2699
  ...(ngDevMode ? [{ debugName: "viewYear" }] : /* istanbul ignore next */ []));
3545
2700
  this.monthName = computed(() => this.months()[this.view().m], /* @ts-ignore */
3546
2701
  ...(ngDevMode ? [{ debugName: "monthName" }] : /* istanbul ignore next */ []));
3547
- /** Początek dekady widocznej w siatce lat (1979 → 1970). */
3548
- this.decadeStart = computed(() => Math.floor(this.view().y / 10) * 10, /* @ts-ignore */
3549
- ...(ngDevMode ? [{ debugName: "decadeStart" }] : /* istanbul ignore next */ []));
3550
- /** Początek strony dekad: 12 dekad, czyli 120 lat (1979 → 1920, strona 1920–2039). */
3551
- this.centuryStart = computed(() => Math.floor(this.view().y / 120) * 120, /* @ts-ignore */
3552
- ...(ngDevMode ? [{ debugName: "centuryStart" }] : /* istanbul ignore next */ []));
3553
- this.yearRangeLabel = computed(() => `${this.decadeStart()} – ${this.decadeStart() + 9}`, /* @ts-ignore */
2702
+ this.yearRangeLabel = computed(() => `${decadeStart(this.view().y)} – ${decadeStart(this.view().y) + 9}`, /* @ts-ignore */
3554
2703
  ...(ngDevMode ? [{ debugName: "yearRangeLabel" }] : /* istanbul ignore next */ []));
3555
- this.decadeRangeLabel = computed(() => `${this.centuryStart()} – ${this.centuryStart() + 119}`, /* @ts-ignore */
2704
+ this.decadeRangeLabel = computed(() => `${centuryStart(this.view().y)} – ${centuryStart(this.view().y) + 119}`, /* @ts-ignore */
3556
2705
  ...(ngDevMode ? [{ debugName: "decadeRangeLabel" }] : /* istanbul ignore next */ []));
3557
2706
  /** Tryb 'month' nie ma po czym nawigować — siatka miesięcy jest kompletna. */
3558
2707
  this.hasNav = computed(() => this.selectionMode() !== 'month', /* @ts-ignore */
@@ -3575,37 +2724,15 @@ class KptDatepicker {
3575
2724
  }
3576
2725
  }, /* @ts-ignore */
3577
2726
  ...(ngDevMode ? [{ debugName: "navNextLabel" }] : /* istanbul ignore next */ []));
3578
- /** Strzałka wstecz gasnie, gdy cała poprzednia strona wypada przed `minDate`. */
3579
- this.canPageBack = computed(() => {
3580
- const min = this.minDate();
3581
- if (!min)
3582
- return true;
3583
- const { y, m } = this.view();
3584
- switch (this.panelView()) {
3585
- case 'month': return `${y - 1}-12` >= min.slice(0, 7);
3586
- case 'year': return this.decadeStart() - 1 >= +min.slice(0, 4);
3587
- case 'decade': return this.centuryStart() - 1 >= +min.slice(0, 4);
3588
- default: return toIso$1(new Date(y, m, 0)) >= min; // ostatni dzień poprzedniego miesiąca
3589
- }
3590
- }, /* @ts-ignore */
2727
+ /** Strzałka gaśnie, gdy cała sąsiednia strona wypada poza zakres (logika w `@konce-pt/datetime`). */
2728
+ this.canPageBack = computed(() => canPageBack(this.view(), this.panelView(), this.minDate()), /* @ts-ignore */
3591
2729
  ...(ngDevMode ? [{ debugName: "canPageBack" }] : /* istanbul ignore next */ []));
3592
- this.canPageForward = computed(() => {
3593
- const max = this.maxDate();
3594
- if (!max)
3595
- return true;
3596
- const { y, m } = this.view();
3597
- switch (this.panelView()) {
3598
- case 'month': return `${y + 1}-01` <= max.slice(0, 7);
3599
- case 'year': return this.decadeStart() + 10 <= +max.slice(0, 4);
3600
- case 'decade': return this.centuryStart() + 120 <= +max.slice(0, 4);
3601
- default: return toIso$1(new Date(y, m + 1, 1)) <= max;
3602
- }
3603
- }, /* @ts-ignore */
2730
+ this.canPageForward = computed(() => canPageForward(this.view(), this.panelView(), this.maxDate()), /* @ts-ignore */
3604
2731
  ...(ngDevMode ? [{ debugName: "canPageForward" }] : /* istanbul ignore next */ []));
3605
2732
  /** Etykieta czasu na pasku trybu datetime (uwzględnia AM/PM). */
3606
2733
  this.timeBarLabel = computed(() => {
3607
- const t = this.parseTime(this.timeStr());
3608
- return this.formatTime(t?.h ?? 0, t?.m ?? 0);
2734
+ const t = parseTime(this.timeStr());
2735
+ return formatTime(t?.h ?? 0, t?.m ?? 0, this.hourFormat() === 12 ? 12 : 24);
3609
2736
  }, /* @ts-ignore */
3610
2737
  ...(ngDevMode ? [{ debugName: "timeBarLabel" }] : /* istanbul ignore next */ []));
3611
2738
  /**
@@ -3637,113 +2764,44 @@ class KptDatepicker {
3637
2764
  // ── Siatka dni (tryby 'date' / 'datetime') ──
3638
2765
  this.selectedDateIso = computed(() => this.selectionMode() === 'datetime' ? this.pendingDate() : this.value(), /* @ts-ignore */
3639
2766
  ...(ngDevMode ? [{ debugName: "selectedDateIso" }] : /* istanbul ignore next */ []));
3640
- this.weeks = computed(() => {
3641
- const { y, m } = this.view();
3642
- const first = new Date(y, m, 1);
3643
- const startOffset = (first.getDay() + 6) % 7; // poniedziałek = 0
3644
- const start = new Date(y, m, 1 - startOffset);
3645
- const sel = this.selectedDateIso();
3646
- const min = this.minDate();
3647
- const max = this.maxDate();
3648
- const todayIso = toIso$1(this.today);
3649
- const weeks = [];
3650
- for (let w = 0; w < 6; w++) {
3651
- const row = [];
3652
- for (let d = 0; d < 7; d++) {
3653
- const date = new Date(start.getFullYear(), start.getMonth(), start.getDate() + w * 7 + d);
3654
- const iso = toIso$1(date);
3655
- row.push({
3656
- day: date.getDate(),
3657
- iso,
3658
- inMonth: date.getMonth() === m,
3659
- today: iso === todayIso,
3660
- selected: iso === sel,
3661
- disabled: (min != null && iso < min) || (max != null && iso > max),
3662
- });
3663
- }
3664
- weeks.push(row);
3665
- }
3666
- return weeks;
3667
- }, /* @ts-ignore */
2767
+ this.weeks = computed(() => buildDayGrid({
2768
+ page: this.view(),
2769
+ selectedIso: this.selectedDateIso(),
2770
+ todayIso: toIso(this.today),
2771
+ minDate: this.minDate(),
2772
+ maxDate: this.maxDate(),
2773
+ }), /* @ts-ignore */
3668
2774
  ...(ngDevMode ? [{ debugName: "weeks" }] : /* istanbul ignore next */ []));
3669
2775
  /** Rok/miesiąc bieżącej wartości — zaznaczenie w siatkach wyższych poziomów. */
3670
- this.selectedYM = computed(() => {
3671
- const v = this.value();
3672
- switch (this.selectionMode()) {
3673
- case 'month': {
3674
- const m = /^(\d{2})$/.exec(v);
3675
- return { y: null, m: m ? +m[1] - 1 : null };
3676
- }
3677
- case 'year':
3678
- return { y: /^\d{4}$/.test(v) ? +v : null, m: null };
3679
- case 'monthYear': {
3680
- const m = /^(\d{4})-(\d{2})$/.exec(v);
3681
- return m ? { y: +m[1], m: +m[2] - 1 } : { y: null, m: null };
3682
- }
3683
- case 'time':
3684
- return { y: null, m: null };
3685
- default: {
3686
- const d = this.parseDate(this.selectedDateIso());
3687
- return d ? { y: d.getFullYear(), m: d.getMonth() } : { y: null, m: null };
3688
- }
3689
- }
3690
- }, /* @ts-ignore */
2776
+ this.selectedYM = computed(() => selectedYearMonth(this.selectedDateIso(), this.selectionMode()), /* @ts-ignore */
3691
2777
  ...(ngDevMode ? [{ debugName: "selectedYM" }] : /* istanbul ignore next */ []));
3692
- // ── Siatka miesięcy ──
3693
- this.monthCells = computed(() => {
3694
- const { y } = this.view();
3695
- const sel = this.selectedYM();
3696
- const isMonthOnly = this.selectionMode() === 'month';
3697
- const numeric = this.monthDisplay() === 'number';
3698
- const todayY = this.today.getFullYear();
3699
- const todayM = this.today.getMonth();
3700
- return this.months().map((name, i) => ({
3701
- label: numeric ? pad$1(i + 1) : name,
3702
- y,
3703
- m: i,
3704
- selected: sel.m === i && (isMonthOnly || sel.y === y),
3705
- current: todayM === i && (isMonthOnly || todayY === y),
3706
- disabled: isMonthOnly ? false : this.isMonthYearDisabled(y, i),
3707
- }));
3708
- }, /* @ts-ignore */
2778
+ // ── Siatki poziomów (miesiące, lata, dekady) ──
2779
+ this.monthCells = computed(() => buildMonthCells({
2780
+ year: this.view().y,
2781
+ monthNames: this.months(),
2782
+ selected: this.selectedYM(),
2783
+ today: this.today,
2784
+ monthOnly: this.selectionMode() === 'month',
2785
+ numeric: this.monthDisplay() === 'number',
2786
+ minDate: this.minDate(),
2787
+ maxDate: this.maxDate(),
2788
+ }), /* @ts-ignore */
3709
2789
  ...(ngDevMode ? [{ debugName: "monthCells" }] : /* istanbul ignore next */ []));
3710
- // ── Siatka lat (pełna dekada) ──
3711
- this.yearCells = computed(() => {
3712
- const start = this.decadeStart();
3713
- const sel = this.selectedYM();
3714
- const todayY = this.today.getFullYear();
3715
- return Array.from({ length: 10 }, (_, i) => {
3716
- const year = start + i;
3717
- return {
3718
- label: String(year),
3719
- y: year,
3720
- m: 0,
3721
- selected: sel.y === year,
3722
- current: todayY === year,
3723
- disabled: this.isYearDisabled(year),
3724
- };
3725
- });
3726
- }, /* @ts-ignore */
2790
+ this.yearCells = computed(() => buildYearCells({
2791
+ year: this.view().y,
2792
+ selected: this.selectedYM(),
2793
+ today: this.today,
2794
+ minDate: this.minDate(),
2795
+ maxDate: this.maxDate(),
2796
+ }), /* @ts-ignore */
3727
2797
  ...(ngDevMode ? [{ debugName: "yearCells" }] : /* istanbul ignore next */ []));
3728
- // ── Siatka dekad (12 dekad = 120 lat) ──
3729
- this.decadeCells = computed(() => {
3730
- const start = this.centuryStart();
3731
- const sel = this.selectedYM();
3732
- const todayY = this.today.getFullYear();
3733
- return Array.from({ length: 12 }, (_, i) => {
3734
- const from = start + i * 10;
3735
- const to = from + 9;
3736
- return {
3737
- label: `${from} – ${to}`,
3738
- y: from,
3739
- m: 0,
3740
- selected: sel.y != null && sel.y >= from && sel.y <= to,
3741
- current: todayY >= from && todayY <= to,
3742
- // Dekada wypada z zakresu dopiero, gdy poza nim są oba jej krańce.
3743
- disabled: this.isYearDisabled(from) && this.isYearDisabled(to),
3744
- };
3745
- });
3746
- }, /* @ts-ignore */
2798
+ this.decadeCells = computed(() => buildDecadeCells({
2799
+ year: this.view().y,
2800
+ selected: this.selectedYM(),
2801
+ today: this.today,
2802
+ minDate: this.minDate(),
2803
+ maxDate: this.maxDate(),
2804
+ }), /* @ts-ignore */
3747
2805
  ...(ngDevMode ? [{ debugName: "decadeCells" }] : /* istanbul ignore next */ []));
3748
2806
  /** Komórki bieżącego poziomu — siatka miesięcy/lat/dekad ma jeden wspólny markup. */
3749
2807
  this.levelCells = computed(() => {
@@ -3764,21 +2822,13 @@ class KptDatepicker {
3764
2822
  untracked(() => {
3765
2823
  if (!isOpen)
3766
2824
  return;
3767
- this.view.set(this.initialView());
3768
- this.panelView.set(this.effectiveStartView());
2825
+ this.view.set(initialPage(this.value(), this.selectionMode(), this.today));
2826
+ this.panelView.set(resolveStartView(this.selectionMode(), this.startView()));
3769
2827
  this.syncTimeFromValue();
3770
2828
  this.dtView.set(this.selectionMode() === 'time' ? 'clock' : 'calendar');
3771
2829
  });
3772
2830
  });
3773
2831
  }
3774
- // ── Prezentacja czasu ──
3775
- formatTime(h, m) {
3776
- if (this.hourFormat() === 12) {
3777
- const h12 = h % 12 === 0 ? 12 : h % 12;
3778
- return `${h12}:${pad$1(m)} ${h < 12 ? 'AM' : 'PM'}`;
3779
- }
3780
- return `${pad$1(h)}:${pad$1(m)}`;
3781
- }
3782
2832
  displayMonthYear(v, iso) {
3783
2833
  const m = /^(\d{4})-(\d{2})$/.exec(v);
3784
2834
  if (!m)
@@ -3792,91 +2842,28 @@ class KptDatepicker {
3792
2842
  return this.monthDisplay() === 'number' ? m[1] : (this.months()[+m[1] - 1] ?? '');
3793
2843
  }
3794
2844
  displayTime(v) {
3795
- const t = this.parseTime(v);
3796
- return t ? this.formatTime(t.h, t.m) : '';
2845
+ const t = parseTime(v);
2846
+ return t ? formatTime(t.h, t.m, this.hourFormat() === 12 ? 12 : 24) : '';
3797
2847
  }
3798
2848
  displayDateTime(v, iso) {
3799
- const dt = this.parseDateTime(v);
2849
+ const dt = parseDateTime(v);
3800
2850
  if (!dt)
3801
2851
  return '';
3802
- const datePart = iso ? dt.date : `${dt.date.slice(8, 10)}.${dt.date.slice(5, 7)}.${dt.date.slice(0, 4)}`;
3803
2852
  const sep = iso ? 'T' : ' ';
3804
- return `${datePart}${sep}${this.formatTime(dt.h, dt.m)}`;
2853
+ return `${formatDate(dt.date, iso ? 'iso' : 'pl')}${sep}${formatTime(dt.h, dt.m, this.hourFormat() === 12 ? 12 : 24)}`;
3805
2854
  }
3806
2855
  displayDate(v, iso) {
3807
- const d = this.parseDate(v);
3808
- if (!d)
3809
- return '';
3810
- return iso ? toIso$1(d) : `${pad$1(d.getDate())}.${pad$1(d.getMonth() + 1)}.${d.getFullYear()}`;
3811
- }
3812
- // ── Parsowanie ──
3813
- parseDate(iso) {
3814
- const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(iso ?? '');
3815
- if (!match)
3816
- return null;
3817
- return new Date(+match[1], +match[2] - 1, +match[3]);
3818
- }
3819
- parseTime(v) {
3820
- const m = /^(\d{2}):(\d{2})$/.exec(v ?? '');
3821
- return m ? { h: +m[1], m: +m[2] } : null;
3822
- }
3823
- parseDateTime(v) {
3824
- const m = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}):(\d{2})$/.exec(v ?? '');
3825
- return m ? { date: m[1], h: +m[2], m: +m[3] } : null;
3826
- }
3827
- isYearDisabled(year) {
3828
- const min = this.minDate();
3829
- const max = this.maxDate();
3830
- if (min && year < +min.slice(0, 4))
3831
- return true;
3832
- if (max && year > +max.slice(0, 4))
3833
- return true;
3834
- return false;
3835
- }
3836
- isMonthYearDisabled(y, monthIndex) {
3837
- const ym = `${y}-${pad$1(monthIndex + 1)}`;
3838
- const min = this.minDate();
3839
- const max = this.maxDate();
3840
- if (min && ym < min.slice(0, 7))
3841
- return true;
3842
- if (max && ym > max.slice(0, 7))
3843
- return true;
3844
- return false;
3845
- }
3846
- initialView() {
3847
- const v = this.value();
3848
- switch (this.selectionMode()) {
3849
- case 'monthYear': {
3850
- const m = /^(\d{4})-(\d{2})$/.exec(v);
3851
- return m ? { y: +m[1], m: +m[2] - 1 } : { y: this.today.getFullYear(), m: this.today.getMonth() };
3852
- }
3853
- case 'year':
3854
- return { y: /^\d{4}$/.test(v) ? +v : this.today.getFullYear(), m: 0 };
3855
- case 'month':
3856
- return { y: this.today.getFullYear(), m: 0 };
3857
- case 'datetime': {
3858
- const dt = this.parseDateTime(v);
3859
- if (dt) {
3860
- const d = this.parseDate(dt.date);
3861
- return { y: d.getFullYear(), m: d.getMonth() };
3862
- }
3863
- return { y: this.today.getFullYear(), m: this.today.getMonth() };
3864
- }
3865
- default: {
3866
- const d = this.parseDate(v) ?? this.today;
3867
- return { y: d.getFullYear(), m: d.getMonth() };
3868
- }
3869
- }
2856
+ return formatDate(v, iso ? 'iso' : 'pl');
3870
2857
  }
3871
2858
  syncTimeFromValue() {
3872
2859
  const mode = this.selectionMode();
3873
2860
  if (mode === 'time') {
3874
- const t = this.parseTime(this.value());
3875
- this.timeStr.set(t ? `${pad$1(t.h)}:${pad$1(t.m)}` : '00:00');
2861
+ const t = parseTime(this.value());
2862
+ this.timeStr.set(t ? `${pad(t.h)}:${pad(t.m)}` : '00:00');
3876
2863
  }
3877
2864
  else if (mode === 'datetime') {
3878
- const dt = this.parseDateTime(this.value());
3879
- this.timeStr.set(dt ? `${pad$1(dt.h)}:${pad$1(dt.m)}` : '00:00');
2865
+ const dt = parseDateTime(this.value());
2866
+ this.timeStr.set(dt ? `${pad(dt.h)}:${pad(dt.m)}` : '00:00');
3880
2867
  this.pendingDate.set(dt?.date ?? '');
3881
2868
  }
3882
2869
  }
@@ -3916,10 +2903,10 @@ class KptDatepicker {
3916
2903
  return;
3917
2904
  }
3918
2905
  this.view.update(({ m }) => ({ y: cell.y, m: level === 'month' ? cell.m : m }));
3919
- this.panelView.set(LEVELS[LEVELS.indexOf(level) - 1]);
2906
+ this.panelView.set(KPT_CALENDAR_LEVELS[KPT_CALENDAR_LEVELS.indexOf(level) - 1]);
3920
2907
  }
3921
2908
  monthValue(cell) {
3922
- const mm = pad$1(cell.m + 1);
2909
+ const mm = pad(cell.m + 1);
3923
2910
  return this.selectionMode() === 'month' ? mm : `${cell.y}-${mm}`;
3924
2911
  }
3925
2912
  /** Klik w tytuł — wejście poziom wyżej w stosie widoków. */
@@ -3939,33 +2926,15 @@ class KptDatepicker {
3939
2926
  this.value.set(time);
3940
2927
  }
3941
2928
  else {
3942
- const dt = this.parseDateTime(this.value());
3943
- const date = this.pendingDate() || dt?.date || toIso$1(this.today);
2929
+ const dt = parseDateTime(this.value());
2930
+ const date = this.pendingDate() || dt?.date || toIso(this.today);
3944
2931
  this.value.set(`${date}T${time}`);
3945
2932
  }
3946
2933
  this.close();
3947
2934
  }
3948
- /** Strzałki ‹ › — krok zależny od poziomu: miesiąc, rok, dekada, strona dekad. */
2935
+ /** Strzałki ‹ › — krok zależny od poziomu (miesiąc, rok, dekada, strona dekad). */
3949
2936
  page(dir) {
3950
- const level = this.panelView();
3951
- this.view.update(({ y, m }) => {
3952
- switch (level) {
3953
- case 'month':
3954
- return { y: y + dir, m };
3955
- case 'year':
3956
- return { y: y + dir * 10, m };
3957
- case 'decade':
3958
- return { y: y + dir * 120, m };
3959
- default: {
3960
- const next = m + dir;
3961
- if (next < 0)
3962
- return { y: y - 1, m: 11 };
3963
- if (next > 11)
3964
- return { y: y + 1, m: 0 };
3965
- return { y, m: next };
3966
- }
3967
- }
3968
- });
2937
+ this.view.update((page) => pageBy(page, this.panelView(), dir));
3969
2938
  }
3970
2939
  pagePrev() {
3971
2940
  this.page(-1);
@@ -4007,9 +2976,9 @@ class KptDatepicker {
4007
2976
  type: Component,
4008
2977
  args: [{ selector: 'kpt-datepicker', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CdkOverlayOrigin, CdkConnectedOverlay, KptIcon, KptButton, KptClock], host: { class: 'kpt-datepicker-host' }, template: "<div\n class=\"kpt-datepicker\"\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n role=\"button\"\n tabindex=\"0\"\n [class.kpt-datepicker--open]=\"open()\"\n [class.kpt-datepicker--disabled]=\"disabled()\"\n [class.kpt-datepicker--invalid]=\"showInvalid()\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.aria-label]=\"ariaLabel()\"\n (click)=\"toggleOpen()\"\n (keydown.enter)=\"toggleOpen()\"\n (blur)=\"touch.emit()\"\n>\n @if (display()) {\n <span class=\"kpt-datepicker__value\">{{ display() }}</span>\n } @else {\n <span class=\"kpt-datepicker__placeholder\">{{ effectivePlaceholder() }}</span>\n }\n <span class=\"kpt-datepicker__spacer\"></span>\n @if (display()) {\n <button type=\"button\" class=\"kpt-datepicker__clear\" (click)=\"clear($event)\" [attr.aria-label]=\"i18n.t('common.clear')\"><kpt-icon name=\"x\" /></button>\n }\n <kpt-icon\n class=\"kpt-datepicker__icon\"\n [name]=\"selectionMode() === 'time' ? 'clock' : 'calendar'\"\n />\n</div>\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"close()\"\n (detach)=\"close()\"\n>\n <div class=\"kpt-calendar\" [class.kpt-calendar--clock]=\"showClock()\" (keydown.escape)=\"close()\">\n @if (showClock()) {\n @if (selectionMode() === 'datetime') {\n <div class=\"kpt-calendar__header\">\n <button type=\"button\" class=\"kpt-calendar__nav\" (click)=\"backToCalendar()\" [attr.aria-label]=\"i18n.t('datepicker.calendar')\"><kpt-icon name=\"chevron-left\" /></button>\n <span class=\"kpt-calendar__title\">{{ i18n.t('datepicker.time') }}</span>\n </div>\n }\n <kpt-clock [(value)]=\"timeStr\" [hourFormat]=\"hourFormat()\" [minuteStep]=\"minuteStep()\" />\n } @else {\n <!-- Nag\u0142\u00F3wek wsp\u00F3lny dla czterech poziom\u00F3w: r\u00F3\u017Cni je tylko tre\u015B\u0107 tytu\u0142u. -->\n <div class=\"kpt-calendar__header\">\n @if (hasNav()) {\n <button type=\"button\" class=\"kpt-calendar__nav\" [disabled]=\"!canPageBack()\" (click)=\"pagePrev()\" [attr.aria-label]=\"navPrevLabel()\"><kpt-icon name=\"chevron-left\" /></button>\n }\n <span class=\"kpt-calendar__titles\">\n @switch (panelView()) {\n @case ('day') {\n <button type=\"button\" class=\"kpt-calendar__title-btn\" (click)=\"goTo('month')\" [attr.aria-label]=\"i18n.t('datepicker.chooseMonth')\">{{ monthName() }}</button>\n <button type=\"button\" class=\"kpt-calendar__title-btn\" (click)=\"goTo('year')\" [attr.aria-label]=\"i18n.t('datepicker.chooseYear')\">{{ viewYear() }}</button>\n }\n @case ('month') {\n @if (selectionMode() === 'month') {\n <span class=\"kpt-calendar__title\">{{ i18n.t('datepicker.month') }}</span>\n } @else {\n <button type=\"button\" class=\"kpt-calendar__title-btn\" (click)=\"goTo('year')\" [attr.aria-label]=\"i18n.t('datepicker.chooseYear')\">{{ viewYear() }}</button>\n }\n }\n @case ('year') {\n <button type=\"button\" class=\"kpt-calendar__title-btn\" (click)=\"goTo('decade')\" [attr.aria-label]=\"i18n.t('datepicker.chooseDecade')\">{{ yearRangeLabel() }}</button>\n }\n @case ('decade') {\n <span class=\"kpt-calendar__title\">{{ decadeRangeLabel() }}</span>\n }\n }\n </span>\n @if (hasNav()) {\n <button type=\"button\" class=\"kpt-calendar__nav\" [disabled]=\"!canPageForward()\" (click)=\"pageNext()\" [attr.aria-label]=\"navNextLabel()\"><kpt-icon name=\"chevron-right\" /></button>\n }\n </div>\n\n @switch (panelView()) {\n @case ('day') {\n <div class=\"kpt-calendar__weekdays\">\n @for (wd of weekdays(); track wd) {\n <span class=\"kpt-calendar__weekday\">{{ wd }}</span>\n }\n </div>\n <div class=\"kpt-calendar__grid\">\n @for (week of weeks(); track $index) {\n @for (cell of week; track cell.iso) {\n <button\n type=\"button\"\n class=\"kpt-calendar__day\"\n [class.kpt-calendar__day--muted]=\"!cell.inMonth\"\n [class.kpt-calendar__day--today]=\"cell.today\"\n [class.kpt-calendar__day--selected]=\"cell.selected\"\n [disabled]=\"cell.disabled\"\n [attr.aria-pressed]=\"cell.selected\"\n (click)=\"selectDay(cell)\"\n >{{ cell.day }}</button>\n }\n }\n </div>\n }\n @default {\n <div class=\"kpt-calendar__grid kpt-calendar__grid--cells\" [class.kpt-calendar__grid--decades]=\"panelView() === 'decade'\">\n @for (cell of levelCells(); track cell.label) {\n <button\n type=\"button\"\n class=\"kpt-calendar__cell\"\n [class.kpt-calendar__cell--selected]=\"cell.selected\"\n [class.kpt-calendar__cell--current]=\"cell.current\"\n [disabled]=\"cell.disabled\"\n [attr.aria-pressed]=\"cell.selected\"\n (click)=\"selectCell(cell)\"\n >{{ cell.label }}</button>\n }\n </div>\n }\n }\n\n @if (selectionMode() === 'datetime') {\n <button type=\"button\" class=\"kpt-calendar__timebar\" (click)=\"openClock()\">\n <kpt-icon name=\"clock\" />\n <span>{{ timeBarLabel() }}</span>\n </button>\n }\n }\n @if (hasFooter()) {\n <div class=\"kpt-calendar__footer\">\n <kpt-button size=\"sm\" (click)=\"commit()\">{{ i18n.t('common.done') }}</kpt-button>\n </div>\n }\n </div>\n</ng-template>\n", styles: ["@layer kpt.components{.kpt-datepicker-host{display:block}.kpt-datepicker{display:flex;align-items:center;gap:var(--kpt-space-2, .5rem);height:2.5rem;padding-inline:var(--kpt-space-3, .75rem);box-sizing:border-box;border:var(--kpt-border-width-thin, 1px) solid var(--kpt-form-field-border);border-radius:var(--kpt-form-field-radius, .5rem);background:var(--kpt-form-field-bg);color:var(--kpt-form-field-text);font-size:var(--kpt-font-size-sm, .875rem);cursor:pointer}.kpt-datepicker:hover:not(.kpt-datepicker--disabled){border-color:var(--kpt-form-field-border-hover)}.kpt-datepicker:focus-visible,.kpt-datepicker.kpt-datepicker--open{outline:none;border-color:var(--kpt-form-field-border-focus);box-shadow:0 0 0 2px color-mix(in oklch,var(--kpt-form-field-border-focus) 30%,transparent)}.kpt-datepicker.kpt-datepicker--invalid{border-color:var(--kpt-form-field-border-error)}.kpt-datepicker.kpt-datepicker--disabled{cursor:not-allowed;opacity:.6;background:var(--kpt-color-surface-variant)}.kpt-datepicker__placeholder{color:var(--kpt-form-field-placeholder)}.kpt-datepicker__spacer{flex:1}.kpt-datepicker__icon{color:var(--kpt-color-on-surface-muted)}.kpt-datepicker__clear{display:inline-flex;border:0;background:none;cursor:pointer;color:var(--kpt-color-on-surface-muted);padding:0}.kpt-datepicker__clear:hover{color:var(--kpt-color-on-surface)}.kpt-calendar{width:17rem;padding:var(--kpt-space-3, .75rem);background:var(--kpt-color-surface-raised);border:var(--kpt-border-width-thin, 1px) solid var(--kpt-color-border);border-radius:var(--kpt-radius-md, .5rem);box-shadow:var(--kpt-elevation-3);color:var(--kpt-color-on-surface);font-size:var(--kpt-font-size-sm, .875rem)}.kpt-calendar__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--kpt-space-2, .5rem)}.kpt-calendar__title{font-weight:var(--kpt-font-weight-semibold, 600);text-transform:capitalize}.kpt-calendar__titles{display:flex;align-items:center;gap:var(--kpt-space-1, .25rem)}.kpt-calendar__title-btn{padding:.25rem var(--kpt-space-2, .5rem);border:0;border-radius:var(--kpt-radius-sm, .25rem);background:var(--kpt-color-muted);color:var(--kpt-color-on-surface);font:inherit;font-weight:var(--kpt-font-weight-semibold, 600);text-transform:capitalize;cursor:pointer}.kpt-calendar__title-btn:hover{background:var(--kpt-color-muted-hover)}.kpt-calendar__title-btn:focus-visible{outline:var(--kpt-border-width-thin, 1px) solid var(--kpt-color-border-strong);outline-offset:1px}.kpt-calendar__nav{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:0;border-radius:var(--kpt-radius-md, .5rem);background:none;color:var(--kpt-color-on-surface);cursor:pointer}.kpt-calendar__nav:hover:not(:disabled){background:var(--kpt-color-muted)}.kpt-calendar__nav:disabled{opacity:.3;cursor:not-allowed}.kpt-calendar__weekdays,.kpt-calendar__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.kpt-calendar__weekday{text-align:center;font-size:var(--kpt-font-size-xs, .75rem);color:var(--kpt-color-on-surface-muted);padding:.25rem 0}.kpt-calendar__day{aspect-ratio:1;border:0;border-radius:var(--kpt-radius-sm, .25rem);background:none;color:var(--kpt-color-on-surface);cursor:pointer;font:inherit}.kpt-calendar__day:hover:not(:disabled){background:var(--kpt-color-muted)}.kpt-calendar__day--muted{color:var(--kpt-color-on-surface-muted);opacity:.5}.kpt-calendar__day--today{box-shadow:inset 0 0 0 1px var(--kpt-color-border-strong)}.kpt-calendar__day--selected{background:var(--kpt-color-primary)!important;color:var(--kpt-color-on-primary)}.kpt-calendar__day:disabled{opacity:.3;cursor:not-allowed}.kpt-calendar__grid--cells{grid-template-columns:repeat(3,1fr);gap:4px}.kpt-calendar__cell{padding:.6rem .25rem;border:0;border-radius:var(--kpt-radius-sm, .25rem);background:none;color:var(--kpt-color-on-surface);cursor:pointer;font:inherit;text-transform:capitalize}.kpt-calendar__cell:hover:not(:disabled){background:var(--kpt-color-muted)}.kpt-calendar__cell--current{box-shadow:inset 0 0 0 1px var(--kpt-color-border-strong)}.kpt-calendar__cell--selected{background:var(--kpt-color-primary)!important;color:var(--kpt-color-on-primary)}.kpt-calendar__cell:disabled{opacity:.3;cursor:not-allowed}.kpt-calendar__grid--decades .kpt-calendar__cell{padding-inline:0;font-size:var(--kpt-font-size-xs, .75rem);white-space:nowrap}.kpt-calendar__timebar{display:flex;align-items:center;justify-content:center;gap:var(--kpt-space-2, .5rem);width:100%;margin-top:var(--kpt-space-2, .5rem);padding:var(--kpt-space-2, .5rem);border:var(--kpt-border-width-thin, 1px) solid var(--kpt-color-border);border-radius:var(--kpt-radius-md, .5rem);background:none;color:var(--kpt-color-on-surface);font:inherit;font-variant-numeric:tabular-nums;cursor:pointer}.kpt-calendar__timebar:hover{background:var(--kpt-color-muted)}.kpt-calendar__timebar kpt-icon{color:var(--kpt-color-on-surface-muted)}.kpt-calendar__footer{display:flex;justify-content:flex-end;margin-top:var(--kpt-space-3, .75rem)}.kpt-calendar--clock{width:16rem}}\n"] }]
4009
2978
  }], () => [], { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], displayFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFormat", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], startView: [{ type: i0.Input, args: [{ isSignal: true, alias: "startView", required: false }] }], monthDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthDisplay", required: false }] }], hourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourFormat", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }] }); })();
4010
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptDatepicker, { className: "KptDatepicker", filePath: "lib/datepicker/datepicker.component.ts", lineNumber: 81 }); })();
2979
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptDatepicker, { className: "KptDatepicker", filePath: "lib/datepicker/datepicker.component.ts", lineNumber: 83 }); })();
4011
2980
 
4012
- const _c0$v = ["ta"];
2981
+ const _c0$w = ["ta"];
4013
2982
  /**
4014
2983
  * Pole wieloliniowe (textarea) na Signal Forms, z opcjonalnym auto-resize.
4015
2984
  *
@@ -4054,7 +3023,7 @@ class KptTextarea {
4054
3023
  }
4055
3024
  static { this.ɵfac = function KptTextarea_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptTextarea)(); }; }
4056
3025
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptTextarea, selectors: [["kpt-textarea"]], viewQuery: function KptTextarea_Query(rf, ctx) { if (rf & 1) {
4057
- i0.ɵɵviewQuerySignal(ctx.ta, _c0$v, 5);
3026
+ i0.ɵɵviewQuerySignal(ctx.ta, _c0$w, 5);
4058
3027
  } if (rf & 2) {
4059
3028
  i0.ɵɵqueryAdvance();
4060
3029
  } }, hostAttrs: [1, "kpt-textarea-host"], inputs: { value: [1, "value"], placeholder: [1, "placeholder"], rows: [1, "rows"], autoResize: [1, "autoResize"], disabled: [1, "disabled"], readonly: [1, "readonly"], invalid: [1, "invalid"], touched: [1, "touched"] }, outputs: { value: "valueChange", touch: "touch" }, decls: 2, vars: 6, consts: [["ta", ""], [1, "kpt-textarea__field", 3, "input", "blur", "value", "placeholder", "disabled", "readOnly", "rows"]], template: function KptTextarea_Template(rf, ctx) { if (rf & 1) {
@@ -4206,7 +3175,7 @@ class KptTooltip {
4206
3175
  }]
4207
3176
  }], null, { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "kptTooltip", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "kptTooltipPosition", required: false }] }], onlyWhenTruncated: [{ type: i0.Input, args: [{ isSignal: true, alias: "kptTooltipOnlyWhenTruncated", required: false }] }] }); })();
4208
3177
 
4209
- const _c0$u = ["editor"];
3178
+ const _c0$v = ["editor"];
4210
3179
  const _forTrack0$8 = ($index, $item) => $item.tag;
4211
3180
  function KptRichText_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
4212
3181
  i0.ɵɵelement(0, "span", 11);
@@ -5814,7 +4783,7 @@ class KptRichText {
5814
4783
  }
5815
4784
  static { this.ɵfac = function KptRichText_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptRichText)(); }; }
5816
4785
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptRichText, selectors: [["kpt-rich-text"]], viewQuery: function KptRichText_Query(rf, ctx) { if (rf & 1) {
5817
- i0.ɵɵviewQuerySignal(ctx.editor, _c0$u, 5);
4786
+ i0.ɵɵviewQuerySignal(ctx.editor, _c0$v, 5);
5818
4787
  } if (rf & 2) {
5819
4788
  i0.ɵɵqueryAdvance();
5820
4789
  } }, hostAttrs: [1, "kpt-rich-text-host"], inputs: { value: [1, "value"], toolbar: [1, "toolbar"], placeholder: [1, "placeholder"], maxListLevel: [1, "maxListLevel"], disabled: [1, "disabled"], invalid: [1, "invalid"], touched: [1, "touched"] }, outputs: { value: "valueChange", touch: "touch" }, decls: 11, vars: 14, consts: [["paletteTpl", ""], ["styleOrigin", "cdkOverlayOrigin"], ["foreOrigin", "cdkOverlayOrigin"], ["backOrigin", "cdkOverlayOrigin"], ["tableOrigin", "cdkOverlayOrigin"], ["editor", ""], [1, "kpt-rich-text"], ["role", "toolbar", 1, "kpt-rich-text__toolbar"], ["spellcheck", "false", 1, "kpt-rich-text__source", 3, "value", "disabled"], ["role", "textbox", "aria-multiline", "true", 1, "kpt-rich-text__editor"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayHasBackdrop"], ["aria-hidden", "true", 1, "kpt-rich-text__divider"], ["type", "button", 1, "kpt-rich-text__tool", 3, "is-active", "kptTooltip", "disabled"], ["type", "button", "cdkOverlayOrigin", "", 1, "kpt-rich-text__style", 3, "mousedown", "click", "disabled", "kptTooltip"], ["name", "chevron-down", 1, "kpt-rich-text__style-caret"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayHasBackdrop"], ["role", "listbox", 1, "kpt-rich-text__style-panel"], ["role", "option", 1, "kpt-rich-text__style-opt", 3, "class", "is-selected"], ["role", "option", 1, "kpt-rich-text__style-opt", 3, "click"], ["type", "button", "cdkOverlayOrigin", "", 1, "kpt-rich-text__tool", "kpt-rich-text__tool--color", 3, "mousedown", "click", "kptTooltip", "disabled"], [3, "name"], [3, "ngTemplateOutlet"], ["type", "button", "cdkOverlayOrigin", "", 1, "kpt-rich-text__tool", 3, "mousedown", "click", "kptTooltip", "disabled"], [1, "kpt-rt-grid-pop", 3, "mousedown"], [1, "kpt-rt-grid", 3, "mouseleave"], [1, "kpt-rt-grid__row"], [1, "kpt-rt-grid__label"], [1, "kpt-rt-grid__cell", 3, "is-on"], [1, "kpt-rt-grid__cell", 3, "mouseenter", "click"], ["type", "button", 1, "kpt-rich-text__tool", 3, "mousedown", "click", "kptTooltip", "disabled"], ["spellcheck", "false", 1, "kpt-rich-text__source", 3, "input", "blur", "value", "disabled"], ["role", "textbox", "aria-multiline", "true", 1, "kpt-rich-text__editor", 3, "input", "keydown", "paste", "contextmenu", "mousedown", "mousemove", "blur"], [1, "kpt-rt-menu", 3, "contextmenu"], [1, "kpt-rt-menu__group"], ["type", "button", 1, "kpt-rt-menu__item", 3, "click"], ["name", "plus"], ["name", "table"], ["name", "trash"], [1, "kpt-rt-menu__sep"], ["name", "palette"], ["name", "align-left"], ["name", "align-center"], ["name", "align-right"], ["name", "grip-vertical"], ["type", "button", 1, "kpt-rt-menu__item", "kpt-rt-menu__item--danger", 3, "click"], [1, "kpt-rt-border", 3, "mousedown"], [1, "kpt-rt-border__seg"], ["type", "button", 3, "click"], [1, "kpt-rt-border__widths"], [1, "kpt-rich-text__swatches"], ["type", "button", 1, "kpt-rich-text__swatch", 3, "background"], [1, "kpt-rich-text__picker"], ["type", "color", 3, "input"], ["type", "button", 1, "kpt-rich-text__swatch", 3, "click"], [1, "kpt-rich-text__palette", 3, "mousedown"]], template: function KptRichText_Template(rf, ctx) { if (rf & 1) {
@@ -6044,6 +5013,7 @@ class KptSlider {
6044
5013
  }], null, { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], range: [{ type: i0.Input, args: [{ isSignal: true, alias: "range", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }] }); })();
6045
5014
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptSlider, { className: "KptSlider", filePath: "lib/slider/slider.component.ts", lineNumber: 87 }); })();
6046
5015
 
5016
+ const _c0$u = (a0, a1) => ({ value: a0, max: a1 });
6047
5017
  function KptRating_For_2_Template(rf, ctx) { if (rf & 1) {
6048
5018
  const _r1 = i0.ɵɵgetCurrentView();
6049
5019
  i0.ɵɵelementStart(0, "button", 2);
@@ -6055,7 +5025,7 @@ function KptRating_For_2_Template(rf, ctx) { if (rf & 1) {
6055
5025
  const ctx_r2 = i0.ɵɵnextContext();
6056
5026
  i0.ɵɵclassProp("is-filled", star_r2 <= (ctx_r2.hover() || ctx_r2.value()));
6057
5027
  i0.ɵɵproperty("disabled", ctx_r2.readonly() || ctx_r2.disabled());
6058
- i0.ɵɵattribute("aria-label", star_r2 + " z " + ctx_r2.count());
5028
+ i0.ɵɵattribute("aria-label", ctx_r2.i18n.t("rating.star", i0.ɵɵpureFunction2(4, _c0$u, star_r2, ctx_r2.count())));
6059
5029
  } }
6060
5030
  /**
6061
5031
  * Ocena gwiazdkami (rating) na Signal Forms.
@@ -6075,6 +5045,7 @@ class KptRating {
6075
5045
  this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
6076
5046
  this.touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
6077
5047
  this.touch = output();
5048
+ this.i18n = inject(KptI18n);
6078
5049
  this.hover = signal(0, /* @ts-ignore */
6079
5050
  ...(ngDevMode ? [{ debugName: "hover" }] : /* istanbul ignore next */ []));
6080
5051
  this.stars = computed(() => Array.from({ length: this.count() }, (_, i) => i + 1), /* @ts-ignore */
@@ -6089,7 +5060,7 @@ class KptRating {
6089
5060
  static { this.ɵfac = function KptRating_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || KptRating)(); }; }
6090
5061
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: KptRating, selectors: [["kpt-rating"]], hostAttrs: [1, "kpt-rating-host"], inputs: { value: [1, "value"], count: [1, "count"], readonly: [1, "readonly"], disabled: [1, "disabled"], touched: [1, "touched"] }, outputs: { value: "valueChange", touch: "touch" }, decls: 3, vars: 2, consts: [["role", "slider", 1, "kpt-rating"], ["type", "button", 1, "kpt-rating__star", 3, "is-filled", "disabled"], ["type", "button", 1, "kpt-rating__star", 3, "click", "mouseenter", "mouseleave", "disabled"], ["name", "star"]], template: function KptRating_Template(rf, ctx) { if (rf & 1) {
6091
5062
  i0.ɵɵelementStart(0, "div", 0);
6092
- i0.ɵɵrepeaterCreate(1, KptRating_For_2_Template, 2, 4, "button", 1, i0.ɵɵrepeaterTrackByIdentity);
5063
+ i0.ɵɵrepeaterCreate(1, KptRating_For_2_Template, 2, 7, "button", 1, i0.ɵɵrepeaterTrackByIdentity);
6093
5064
  i0.ɵɵelementEnd();
6094
5065
  } if (rf & 2) {
6095
5066
  i0.ɵɵattribute("aria-valuenow", ctx.value())("aria-valuemax", ctx.count());
@@ -6110,13 +5081,13 @@ class KptRating {
6110
5081
  (click)="pick(star)"
6111
5082
  (mouseenter)="hover.set(star)"
6112
5083
  (mouseleave)="hover.set(0)"
6113
- [attr.aria-label]="star + ' z ' + count()"
5084
+ [attr.aria-label]="i18n.t('rating.star', { value: star, max: count() })"
6114
5085
  ><kpt-icon name="star" /></button>
6115
5086
  }
6116
5087
  </div>
6117
5088
  `, host: { class: 'kpt-rating-host' }, styles: ["@layer kpt.components{.kpt-rating-host{display:inline-flex}.kpt-rating{display:inline-flex;gap:.15rem;font-size:1.4rem}.kpt-rating__star{display:inline-flex;border:0;background:none;padding:.1rem;cursor:pointer;color:var(--kpt-color-border-strong);transition:color var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard)}.kpt-rating__star.is-filled{color:var(--kpt-color-warning)}.kpt-rating__star.is-filled svg{fill:currentColor}.kpt-rating__star:disabled{cursor:default}}\n"] }]
6118
5089
  }], null, { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }] }); })();
6119
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptRating, { className: "KptRating", filePath: "lib/rating/rating.component.ts", lineNumber: 46 }); })();
5090
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptRating, { className: "KptRating", filePath: "lib/rating/rating.component.ts", lineNumber: 48 }); })();
6120
5091
 
6121
5092
  const _forTrack0$7 = ($index, $item) => $item.name;
6122
5093
  function KptFileUpload_Conditional_5_Template(rf, ctx) { if (rf & 1) {
@@ -6610,8 +5581,6 @@ function KptDateRange_ng_template_7_Template(rf, ctx) { if (rf & 1) {
6610
5581
  i0.ɵɵadvance();
6611
5582
  i0.ɵɵconditional(ctx_r0.mode() === "time" ? 1 : 2);
6612
5583
  } }
6613
- const pad = (n) => String(n).padStart(2, '0');
6614
- const toIso = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
6615
5584
  /**
6616
5585
  * Wybór zakresu dat z kalendarzem (CDK Overlay), Signal Forms.
6617
5586
  * `mode`: 'date' (domyślnie), 'datetime' (data+godzina, tarcza zegara), 'time' (sama godzina).
@@ -6676,10 +5645,7 @@ class KptDateRange {
6676
5645
  { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },
6677
5646
  { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },
6678
5647
  ];
6679
- this.panelCount = computed(() => {
6680
- const n = Math.trunc(this.visibleMonths());
6681
- return Number.isFinite(n) ? Math.min(3, Math.max(1, n)) : 1;
6682
- }, /* @ts-ignore */
5648
+ this.panelCount = computed(() => clampVisibleMonths(this.visibleMonths()), /* @ts-ignore */
6683
5649
  ...(ngDevMode ? [{ debugName: "panelCount" }] : /* istanbul ignore next */ []));
6684
5650
  this.multi = computed(() => this.panelCount() > 1, /* @ts-ignore */
6685
5651
  ...(ngDevMode ? [{ debugName: "multi" }] : /* istanbul ignore next */ []));
@@ -6693,8 +5659,8 @@ class KptDateRange {
6693
5659
  }
6694
5660
  if (mode === 'datetime') {
6695
5661
  const one = (v) => {
6696
- const d = this.fmtDate(this.datePart(v));
6697
- const t = this.fmtTime(this.timePart(v));
5662
+ const d = this.fmtDate(datePart(v));
5663
+ const t = this.fmtTime(timePart(v));
6698
5664
  return t ? `${d} ${t}` : d;
6699
5665
  };
6700
5666
  return end ? `${one(start)} – ${one(end)}` : `${one(start)} – …`;
@@ -6709,6 +5675,7 @@ class KptDateRange {
6709
5675
  */
6710
5676
  this.panels = computed(() => {
6711
5677
  const { y, m } = this.view();
5678
+ const datetime = this.mode() === 'datetime';
6712
5679
  return Array.from({ length: this.panelCount() }, (_, i) => {
6713
5680
  const first = new Date(y, m + i, 1);
6714
5681
  const py = first.getFullYear();
@@ -6716,84 +5683,40 @@ class KptDateRange {
6716
5683
  return {
6717
5684
  key: `${py}-${pad(pm + 1)}`,
6718
5685
  label: `${this.months()[pm]} ${py}`,
6719
- weeks: this.buildWeeks(py, pm),
5686
+ weeks: buildRangeGrid({
5687
+ page: { y: py, m: pm },
5688
+ start: datetime ? this.startDate() : this.value().start,
5689
+ end: datetime ? this.endDate() : this.value().end,
5690
+ todayIso: toIso(this.today),
5691
+ // Przy kilku panelach dni sąsiednich miesięcy stają się pustymi slotami — inaczej ta
5692
+ // sama data byłaby klikalna dwa razy, a pasmo malowałoby się w obu miejscach.
5693
+ hideOutside: this.multi(),
5694
+ }),
6720
5695
  };
6721
5696
  });
6722
5697
  }, /* @ts-ignore */
6723
5698
  ...(ngDevMode ? [{ debugName: "panels" }] : /* istanbul ignore next */ []));
6724
5699
  }
6725
- datePart(v) {
6726
- return v ? v.slice(0, 10) : '';
6727
- }
6728
- timePart(v) {
6729
- const m = /[T ](\d{2}:\d{2})$/.exec(v);
6730
- return m ? m[1] : '';
6731
- }
6732
5700
  fmtDate(iso) {
6733
- const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(iso);
6734
- if (!m)
6735
- return '';
6736
- return this.displayFormat() === 'iso' ? `${m[1]}-${m[2]}-${m[3]}` : `${m[3]}.${m[2]}.${m[1]}`;
5701
+ return formatDate(iso, this.displayFormat());
6737
5702
  }
6738
5703
  fmtTime(hhmm) {
6739
- const m = /^(\d{2}):(\d{2})$/.exec(hhmm);
6740
- if (!m)
6741
- return '';
6742
- if (this.hourFormat() === 12) {
6743
- const h = +m[1];
6744
- const h12 = h % 12 === 0 ? 12 : h % 12;
6745
- return `${h12}:${m[2]} ${h < 12 ? 'AM' : 'PM'}`;
6746
- }
6747
- return hhmm;
6748
- }
6749
- buildWeeks(y, m) {
6750
- const datetime = this.mode() === 'datetime';
6751
- const start = datetime ? this.startDate() : this.value().start;
6752
- const end = datetime ? this.endDate() : this.value().end;
6753
- const hasBand = !!start && !!end && start < end;
6754
- const hideOutside = this.multi();
6755
- const todayIso = toIso(this.today);
6756
- const first = new Date(y, m, 1);
6757
- const startOffset = (first.getDay() + 6) % 7;
6758
- const gridStart = new Date(y, m, 1 - startOffset);
6759
- const weeks = [];
6760
- for (let w = 0; w < 6; w++) {
6761
- const row = [];
6762
- for (let d = 0; d < 7; d++) {
6763
- const date = new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + w * 7 + d);
6764
- const iso = toIso(date);
6765
- const inMonth = date.getMonth() === m;
6766
- row.push({
6767
- day: date.getDate(),
6768
- iso,
6769
- inMonth,
6770
- today: iso === todayIso,
6771
- isStart: iso === start,
6772
- isEnd: iso === end,
6773
- inRange: hasBand && iso > start && iso < end,
6774
- rangeStart: hasBand && iso === start,
6775
- rangeEnd: hasBand && iso === end,
6776
- blank: hideOutside && !inMonth,
6777
- disabled: false,
6778
- });
6779
- }
6780
- weeks.push(row);
6781
- }
6782
- return weeks;
5704
+ const t = parseTime(hhmm);
5705
+ return t ? formatTime(t.h, t.m, this.hourFormat() === 12 ? 12 : 24) : '';
6783
5706
  }
6784
5707
  toggleOpen() {
6785
5708
  if (this.disabled())
6786
5709
  return;
6787
5710
  if (!this.open()) {
6788
5711
  const { start, end } = this.value();
6789
- const base = this.datePart(start) || toIso(this.today);
5712
+ const base = datePart(start) || toIso(this.today);
6790
5713
  const d = new Date(base);
6791
5714
  this.view.set({ y: d.getFullYear(), m: d.getMonth() });
6792
5715
  if (this.mode() === 'datetime') {
6793
- this.startDate.set(this.datePart(start));
6794
- this.endDate.set(this.datePart(end));
6795
- this.startTime.set(this.timePart(start) || '00:00');
6796
- this.endTime.set(this.timePart(end) || '00:00');
5716
+ this.startDate.set(datePart(start));
5717
+ this.endDate.set(datePart(end));
5718
+ this.startTime.set(timePart(start) || '00:00');
5719
+ this.endTime.set(timePart(end) || '00:00');
6797
5720
  }
6798
5721
  else if (this.mode() === 'time') {
6799
5722
  this.startTime.set(/^\d{2}:\d{2}$/.test(start) ? start : '00:00');
@@ -6813,32 +5736,16 @@ class KptDateRange {
6813
5736
  if (cell.blank || cell.disabled)
6814
5737
  return;
6815
5738
  if (this.mode() === 'datetime') {
6816
- const start = this.startDate();
6817
- const end = this.endDate();
6818
- if (!start || (start && end)) {
6819
- this.startDate.set(cell.iso);
6820
- this.endDate.set('');
6821
- }
6822
- else if (cell.iso < start) {
6823
- this.endDate.set(start);
6824
- this.startDate.set(cell.iso);
6825
- }
6826
- else {
6827
- this.endDate.set(cell.iso);
6828
- }
6829
- return; // czas do wyboru → zamknięcie przez „Gotowe"
6830
- }
6831
- const { start, end } = this.value();
6832
- if (!start || (start && end)) {
6833
- this.value.set({ start: cell.iso, end: '' });
5739
+ // Część kalendarzowa czeka na godziny — wartość powstaje dopiero przy „Gotowe".
5740
+ const next = pickRangeDay({ start: this.startDate(), end: this.endDate() }, cell.iso);
5741
+ this.startDate.set(next.start);
5742
+ this.endDate.set(next.end);
5743
+ return;
6834
5744
  }
6835
- else {
6836
- if (cell.iso < start)
6837
- this.value.set({ start: cell.iso, end: start });
6838
- else
6839
- this.value.set({ start, end: cell.iso });
5745
+ const next = pickRangeDay(this.value(), cell.iso);
5746
+ this.value.set(next);
5747
+ if (next.end)
6840
5748
  this.close();
6841
- }
6842
5749
  }
6843
5750
  commit() {
6844
5751
  if (this.mode() === 'time') {
@@ -6898,7 +5805,7 @@ class KptDateRange {
6898
5805
  type: Component,
6899
5806
  args: [{ selector: 'kpt-date-range', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CdkOverlayOrigin, CdkConnectedOverlay, KptIcon, KptButton, KptClock], host: { class: 'kpt-date-range-host' }, template: "<div\n class=\"kpt-date-range\"\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n role=\"button\"\n tabindex=\"0\"\n [class.kpt-date-range--open]=\"open()\"\n [class.kpt-date-range--disabled]=\"disabled()\"\n [class.kpt-date-range--invalid]=\"showInvalid()\"\n (click)=\"toggleOpen()\"\n (keydown.enter)=\"toggleOpen()\"\n (blur)=\"touch.emit()\"\n>\n @if (display()) {\n <span class=\"kpt-date-range__value\">{{ display() }}</span>\n } @else {\n <span class=\"kpt-date-range__placeholder\">{{ effectivePlaceholder() }}</span>\n }\n <span class=\"kpt-date-range__spacer\"></span>\n @if (display()) {\n <button type=\"button\" class=\"kpt-date-range__clear\" (click)=\"clear($event)\" [attr.aria-label]=\"i18n.t('common.clear')\"><kpt-icon name=\"x\" /></button>\n }\n <kpt-icon class=\"kpt-date-range__icon\" name=\"calendar\" />\n</div>\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"close()\"\n (detach)=\"close()\"\n>\n <div\n class=\"kpt-calendar\"\n [class.kpt-calendar--clock]=\"mode() === 'time'\"\n [class.kpt-calendar--range]=\"mode() !== 'time'\"\n [class.kpt-calendar--multi]=\"multi() && mode() !== 'time'\"\n (keydown.escape)=\"close()\"\n >\n @if (mode() === 'time') {\n <div class=\"kpt-range-tabs\">\n <button type=\"button\" [class.is-active]=\"timeEnd() === 'start'\" (click)=\"timeEnd.set('start')\">{{ i18n.t('dateRange.from') }}</button>\n <button type=\"button\" [class.is-active]=\"timeEnd() === 'end'\" (click)=\"timeEnd.set('end')\">{{ i18n.t('dateRange.to') }}</button>\n </div>\n @if (timeEnd() === 'start') {\n <kpt-clock [value]=\"startTime()\" (valueChange)=\"startTime.set($event)\" [hourFormat]=\"hourFormat()\" [minuteStep]=\"minuteStep()\" />\n } @else {\n <kpt-clock [value]=\"endTime()\" (valueChange)=\"endTime.set($event)\" [hourFormat]=\"hourFormat()\" [minuteStep]=\"minuteStep()\" />\n }\n <div class=\"kpt-calendar__footer\">\n <kpt-button size=\"sm\" (click)=\"commit()\">{{ i18n.t('common.done') }}</kpt-button>\n </div>\n } @else {\n <div class=\"kpt-calendar__panels\">\n @for (panel of panels(); track panel.key; let first = $first, last = $last) {\n <div class=\"kpt-calendar__panel\">\n <!-- Strza\u0142ki tylko na skrajnych panelach; puste sloty trzymaj\u0105 tytu\u0142 na \u015Brodku. -->\n <div class=\"kpt-calendar__header\">\n @if (first) {\n <button type=\"button\" class=\"kpt-calendar__nav\" (click)=\"prevMonth()\" [attr.aria-label]=\"i18n.t('datepicker.prevMonth')\"><kpt-icon name=\"chevron-left\" /></button>\n } @else {\n <span class=\"kpt-calendar__nav-slot\"></span>\n }\n <span class=\"kpt-calendar__title\">{{ panel.label }}</span>\n @if (last) {\n <button type=\"button\" class=\"kpt-calendar__nav\" (click)=\"nextMonth()\" [attr.aria-label]=\"i18n.t('datepicker.nextMonth')\"><kpt-icon name=\"chevron-right\" /></button>\n } @else {\n <span class=\"kpt-calendar__nav-slot\"></span>\n }\n </div>\n <div class=\"kpt-calendar__weekdays\">\n @for (wd of weekdays(); track wd) {\n <span class=\"kpt-calendar__weekday\">{{ wd }}</span>\n }\n </div>\n <div class=\"kpt-calendar__grid\">\n @for (week of panel.weeks; track $index) {\n @for (cell of week; track cell.iso) {\n @if (cell.blank) {\n <span class=\"kpt-calendar__day kpt-calendar__day--blank\"></span>\n } @else {\n <button\n type=\"button\"\n class=\"kpt-calendar__day\"\n [class.kpt-calendar__day--muted]=\"!cell.inMonth\"\n [class.kpt-calendar__day--today]=\"cell.today\"\n [class.kpt-calendar__day--range]=\"cell.inRange\"\n [class.kpt-calendar__day--range-start]=\"cell.rangeStart\"\n [class.kpt-calendar__day--range-end]=\"cell.rangeEnd\"\n [class.kpt-calendar__day--selected]=\"cell.isStart || cell.isEnd\"\n (click)=\"selectDay(cell)\"\n >{{ cell.day }}</button>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n\n @if (mode() === 'datetime') {\n <div class=\"kpt-range-tabs\">\n <button type=\"button\" [class.is-active]=\"timeEnd() === 'start'\" (click)=\"timeEnd.set('start')\">{{ i18n.t('dateRange.fromTime') }}</button>\n <button type=\"button\" [class.is-active]=\"timeEnd() === 'end'\" (click)=\"timeEnd.set('end')\">{{ i18n.t('dateRange.toTime') }}</button>\n </div>\n @if (timeEnd() === 'start') {\n <kpt-clock [value]=\"startTime()\" (valueChange)=\"startTime.set($event)\" [hourFormat]=\"hourFormat()\" [minuteStep]=\"minuteStep()\" />\n } @else {\n <kpt-clock [value]=\"endTime()\" (valueChange)=\"endTime.set($event)\" [hourFormat]=\"hourFormat()\" [minuteStep]=\"minuteStep()\" />\n }\n <div class=\"kpt-calendar__footer\">\n <kpt-button size=\"sm\" (click)=\"commit()\">{{ i18n.t('common.done') }}</kpt-button>\n </div>\n }\n }\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";@layer kpt.components{.kpt-date-range-host{display:block}.kpt-date-range{display:flex;align-items:center;gap:var(--kpt-space-2, .5rem);height:2.5rem;padding-inline:var(--kpt-space-3, .75rem);box-sizing:border-box;border:var(--kpt-border-width-thin, 1px) solid var(--kpt-form-field-border);border-radius:var(--kpt-form-field-radius, .5rem);background:var(--kpt-form-field-bg);color:var(--kpt-form-field-text);font-size:var(--kpt-font-size-sm, .875rem);cursor:pointer}.kpt-date-range:hover:not(.kpt-date-range--disabled){border-color:var(--kpt-form-field-border-hover)}.kpt-date-range:focus-visible,.kpt-date-range.kpt-date-range--open{outline:none;border-color:var(--kpt-form-field-border-focus);box-shadow:0 0 0 2px color-mix(in oklch,var(--kpt-form-field-border-focus) 30%,transparent)}.kpt-date-range.kpt-date-range--invalid{border-color:var(--kpt-form-field-border-error)}.kpt-date-range.kpt-date-range--disabled{cursor:not-allowed;opacity:.6;background:var(--kpt-color-surface-variant)}.kpt-date-range__placeholder{color:var(--kpt-form-field-placeholder)}.kpt-date-range__spacer{flex:1}.kpt-date-range__icon{color:var(--kpt-color-on-surface-muted)}.kpt-date-range__clear{display:inline-flex;border:0;background:none;cursor:pointer;padding:0;color:var(--kpt-color-on-surface-muted)}.kpt-date-range__clear:hover{color:var(--kpt-color-on-surface)}.kpt-calendar{width:17rem;padding:var(--kpt-space-3, .75rem);background:var(--kpt-color-surface-raised);border:var(--kpt-border-width-thin, 1px) solid var(--kpt-color-border);border-radius:var(--kpt-radius-md, .5rem);box-shadow:var(--kpt-elevation-3);color:var(--kpt-color-on-surface);font-size:var(--kpt-font-size-sm, .875rem)}.kpt-calendar__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--kpt-space-2, .5rem)}.kpt-calendar__title{font-weight:var(--kpt-font-weight-semibold, 600);text-transform:capitalize}.kpt-calendar__nav{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:0;border-radius:var(--kpt-radius-md, .5rem);background:none;color:var(--kpt-color-on-surface);cursor:pointer}.kpt-calendar__nav:hover{background:var(--kpt-color-muted)}.kpt-calendar__nav-slot{width:2rem;height:2rem}.kpt-calendar__panels{display:flex;flex-wrap:wrap;gap:var(--kpt-space-4, 1rem)}.kpt-calendar__panel{flex:none;width:15.5rem}.kpt-calendar__weekdays,.kpt-calendar__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.kpt-calendar__weekday{text-align:center;font-size:var(--kpt-font-size-xs, .75rem);color:var(--kpt-color-on-surface-muted);padding:.25rem 0}.kpt-calendar__day{position:relative;isolation:isolate;aspect-ratio:1;border:0;border-radius:var(--kpt-radius-sm, .25rem);background:none;color:var(--kpt-color-on-surface);cursor:pointer;font:inherit}.kpt-calendar__day:hover:not(:disabled){background:var(--kpt-color-muted)}.kpt-calendar__day--muted{color:var(--kpt-color-on-surface-muted);opacity:.5}.kpt-calendar__day--blank{cursor:default;pointer-events:none}.kpt-calendar__day--today{box-shadow:inset 0 0 0 1px var(--kpt-color-border-strong)}.kpt-calendar__day--selected{background:var(--kpt-color-primary)!important;color:var(--kpt-color-on-primary)}.kpt-calendar__footer{display:flex;justify-content:flex-end;margin-top:var(--kpt-space-3, .75rem)}.kpt-calendar--clock{width:16rem}.kpt-calendar--multi{width:auto;max-width:calc(100vw - 2rem)}.kpt-calendar--range .kpt-calendar__day--range:before,.kpt-calendar--range .kpt-calendar__day--range-start:before,.kpt-calendar--range .kpt-calendar__day--range-end:before{content:\"\";position:absolute;inset-block:0;inset-inline:-1px;z-index:-2;background:color-mix(in oklch,var(--kpt-color-primary) 14%,transparent)}.kpt-calendar--range .kpt-calendar__day--range-start:before{inset-inline-start:50%}.kpt-calendar--range .kpt-calendar__day--range-end:before{inset-inline-end:50%}.kpt-calendar--range .kpt-calendar__day--selected{background:none!important;color:var(--kpt-color-on-primary)}.kpt-calendar--range .kpt-calendar__day--selected:after{content:\"\";position:absolute;inset:0;z-index:-1;border-radius:var(--kpt-radius-sm, .25rem);background:var(--kpt-color-primary)}.kpt-calendar--range .kpt-calendar__grid>.kpt-calendar__day:nth-child(7n+1):before{border-start-start-radius:var(--kpt-radius-sm, .25rem);border-end-start-radius:var(--kpt-radius-sm, .25rem)}.kpt-calendar--range .kpt-calendar__grid>.kpt-calendar__day:nth-child(7n):before{border-start-end-radius:var(--kpt-radius-sm, .25rem);border-end-end-radius:var(--kpt-radius-sm, .25rem)}.kpt-range-tabs{display:flex;gap:var(--kpt-space-1, .25rem);margin-block:var(--kpt-space-3, .75rem) var(--kpt-space-2, .5rem);padding:2px;background:var(--kpt-color-surface-variant);border-radius:var(--kpt-radius-md, .5rem)}.kpt-range-tabs button{flex:1;border:0;background:none;padding:var(--kpt-space-1, .25rem) var(--kpt-space-2, .5rem);border-radius:var(--kpt-radius-sm, .25rem);color:var(--kpt-color-on-surface-muted);font:inherit;font-size:var(--kpt-font-size-sm, .875rem);cursor:pointer}.kpt-range-tabs button.is-active{background:var(--kpt-color-surface-raised);color:var(--kpt-color-on-surface);font-weight:var(--kpt-font-weight-medium, 500);box-shadow:var(--kpt-elevation-1)}}\n"] }]
6900
5807
  }], null, { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], displayFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFormat", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], visibleMonths: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleMonths", required: false }] }], hourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourFormat", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }] }); })();
6901
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptDateRange, { className: "KptDateRange", filePath: "lib/date-range/date-range.component.ts", lineNumber: 79 }); })();
5808
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptDateRange, { className: "KptDateRange", filePath: "lib/date-range/date-range.component.ts", lineNumber: 66 }); })();
6902
5809
 
6903
5810
  function KptInputNumber_Conditional_1_Template(rf, ctx) { if (rf & 1) {
6904
5811
  const _r1 = i0.ɵɵgetCurrentView();
@@ -10349,190 +9256,6 @@ class KptCellEditDef {
10349
9256
  }]
10350
9257
  }], null, { kptCellEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "kptCellEdit", required: true }] }] }); })();
10351
9258
 
10352
- /*
10353
- * Zamiana wartości komórki na tekst dla filtrowania, sortowania i podsumowań — pure TS,
10354
- * wydzielone żeby dało się testować `node --test` bez ciągnięcia Angulara (jak `csv-export.ts`).
10355
- */
10356
- /**
10357
- * Tekst z dowolnej wartości komórki. Prymitywy, `Date` i tablice zachowują się jak `String()`,
10358
- * natomiast zwykły obiekt daje **pusty string**, nie `'[object Object]'`: ten drugi udawałby
10359
- * sensowną zawartość — filtr tekstowy „obj" dopasowywałby każdy wiersz z obiektem w komórce,
10360
- * a sortowanie uznawało je wszystkie za równe.
10361
- */
10362
- function toText(value) {
10363
- switch (typeof value) {
10364
- case 'string':
10365
- return value;
10366
- case 'number':
10367
- case 'boolean':
10368
- case 'bigint':
10369
- return String(value);
10370
- case 'object':
10371
- if (value === null)
10372
- return '';
10373
- if (value instanceof Date)
10374
- return value.toString();
10375
- if (Array.isArray(value))
10376
- return value.map(toText).join(',');
10377
- return '';
10378
- default:
10379
- return '';
10380
- }
10381
- }
10382
-
10383
- /*
10384
- * Agregacje wiersza podsumowania (`<tfoot>`) — pure TS, wydzielone żeby dało się
10385
- * testować `node --test` bez ciągnięcia Angulara (jak `csv-export.ts`).
10386
- */
10387
- /**
10388
- * Sumowanie liczb zmiennoprzecinkowych daje ogony (`0.1 + 0.2` → `0.30000000000000004`),
10389
- * które bez tego przycięcia wyciekłyby wprost do komórki podsumowania.
10390
- */
10391
- function trimFloat(value) {
10392
- return Math.round(value * 1e10) / 1e10;
10393
- }
10394
- /** Liczba z komórki: `number` bez zmian, string przez `parseFloat`, reszta → `NaN` (pomijana). */
10395
- function toNumber(value) {
10396
- if (typeof value === 'number')
10397
- return value;
10398
- if (typeof value === 'string' && value.trim() !== '')
10399
- return Number.parseFloat(value);
10400
- return Number.NaN;
10401
- }
10402
- /**
10403
- * Agreguje jedno pole po wierszach. `count` liczy wiersze; pozostałe funkcje pomijają
10404
- * wartości nieliczbowe. Pusty zbiór liczb: `sum` → 0, `avg`/`min`/`max` → `null`
10405
- * (komórka renderuje się wtedy pusta).
10406
- */
10407
- function aggregate(rows, field, fn) {
10408
- if (fn === 'count')
10409
- return rows.length;
10410
- const nums = [];
10411
- for (const row of rows) {
10412
- const num = toNumber(row[field]);
10413
- if (!Number.isNaN(num))
10414
- nums.push(num);
10415
- }
10416
- switch (fn) {
10417
- case 'sum':
10418
- return trimFloat(nums.reduce((acc, n) => acc + n, 0));
10419
- case 'avg':
10420
- return nums.length === 0 ? null : trimFloat(nums.reduce((acc, n) => acc + n, 0) / nums.length);
10421
- case 'min':
10422
- return nums.length === 0 ? null : Math.min(...nums);
10423
- case 'max':
10424
- return nums.length === 0 ? null : Math.max(...nums);
10425
- default:
10426
- return null;
10427
- }
10428
- }
10429
-
10430
- /*
10431
- * Dopasowanie wiersza do filtrów kolumn tabeli — pure TS, wydzielone żeby dało się
10432
- * testować `node --test` bez ciągnięcia Angulara (jak `csv-export.ts` i `summary.ts`).
10433
- * Komponent trzyma tylko stan filtrów; cała semantyka „czy komórka pasuje" jest tutaj.
10434
- */
10435
- /** Data komórki w formacie `YYYY-MM-DD` — do porównań leksykograficznych z granicami zakresu. */
10436
- function toIsoDate(value) {
10437
- if (value instanceof Date) {
10438
- const p = (n) => String(n).padStart(2, '0');
10439
- return `${value.getFullYear()}-${p(value.getMonth() + 1)}-${p(value.getDate())}`;
10440
- }
10441
- return toText(value);
10442
- }
10443
- /** Filtr „pusty" (nie wybrano nic) przepuszcza każdy wiersz. */
10444
- function isEmptyFilterValue(value) {
10445
- return value == null || value === '' || (Array.isArray(value) && value.length === 0);
10446
- }
10447
- const matchesText = (cell, value) => toText(cell).toLowerCase().includes(toText(value).toLowerCase());
10448
- const matchesNumber = (cell, value) => toText(cell).includes(toText(value));
10449
- const matchesSelect = (cell, value) => {
10450
- const picked = Array.isArray(value) ? value : [value];
10451
- // Komórka-tablica (np. lista tagów/członków) → dopasuj, gdy zawiera dowolną z wybranych wartości.
10452
- if (Array.isArray(cell))
10453
- return cell.some((c) => picked.includes(c));
10454
- return picked.includes(cell);
10455
- };
10456
- const matchesNumberRange = (cell, value) => {
10457
- const { min, max } = value ?? {};
10458
- const lo = min == null || min === '' ? null : Number.parseFloat(min);
10459
- const hi = max == null || max === '' ? null : Number.parseFloat(max);
10460
- if (lo === null && hi === null)
10461
- return true;
10462
- const num = toNumber(cell);
10463
- if (Number.isNaN(num))
10464
- return false;
10465
- if (lo !== null && num < lo)
10466
- return false;
10467
- if (hi !== null && num > hi)
10468
- return false;
10469
- return true;
10470
- };
10471
- const matchesSlider = (cell, value) => {
10472
- const [lo, hi] = value;
10473
- const num = toNumber(cell);
10474
- if (Number.isNaN(num))
10475
- return false;
10476
- return num >= lo && num <= hi;
10477
- };
10478
- const matchesDateRange = (cell, value) => {
10479
- const { start, end } = value ?? {};
10480
- if (!start && !end)
10481
- return true;
10482
- const iso = toIsoDate(cell);
10483
- if (start && iso < start)
10484
- return false;
10485
- if (end && iso > end)
10486
- return false;
10487
- return true;
10488
- };
10489
- /** Mapa zamiast `switch` — `Record` po unii typów wymusza komplet, więc nie ma martwego `default`. */
10490
- const MATCHERS = {
10491
- text: matchesText,
10492
- number: matchesNumber,
10493
- select: matchesSelect,
10494
- numberRange: matchesNumberRange,
10495
- slider: matchesSlider,
10496
- dateRange: matchesDateRange,
10497
- };
10498
- /** Czy komórka przechodzi filtr kolumny. Wartości pustych filtrów odsiewa `isEmptyFilterValue`. */
10499
- function matchesColumnFilter(filter, cell, value) {
10500
- return MATCHERS[filter.type](cell, value);
10501
- }
10502
-
10503
- /*
10504
- * Escapowanie komórek CSV dla `exportCsv()` — pure TS, wydzielone żeby dało się
10505
- * testować `node --test` bez ciągnięcia Angulara.
10506
- */
10507
- // Znak startowy, który arkusz kalkulacyjny czyta jako początek formuły (CWE-1236).
10508
- const FORMULA_PREFIX = /^[=+\-@\t\r]/;
10509
- function stringifyCsvValue(value) {
10510
- switch (typeof value) {
10511
- case 'undefined':
10512
- return '';
10513
- case 'string':
10514
- return value;
10515
- case 'number':
10516
- case 'boolean':
10517
- case 'bigint':
10518
- return String(value);
10519
- default:
10520
- if (value === null)
10521
- return '';
10522
- if (value instanceof Date)
10523
- return value.toISOString();
10524
- return JSON.stringify(value);
10525
- }
10526
- }
10527
- /** Escapuje pojedynczą wartość komórki/nagłówka do bezpiecznego pola CSV (separator `;`). */
10528
- function escapeCsvCell(value) {
10529
- let text = stringifyCsvValue(value);
10530
- // Wiodący `'` każe arkuszowi traktować komórkę jako tekst — sam znak nie jest wyświetlany.
10531
- if (FORMULA_PREFIX.test(text))
10532
- text = `'${text}`;
10533
- return /[",\n;]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
10534
- }
10535
-
10536
9259
  /**
10537
9260
  * Szablon rozwijanego wiersza (row detail) dla `kpt-data-table`. Renderowany pod
10538
9261
  * wierszem po rozwinięciu. Kontekst: `$implicit` = wiersz. Wymaga `expandable`.
@@ -11685,7 +10408,7 @@ class KptDataTable {
11685
10408
  const v = this.columnFilters()[col.field];
11686
10409
  return v ?? [mn, mx];
11687
10410
  }
11688
- /** Semantyka dopasowania siedzi w `./column-filter` — tu zostaje tylko spięcie ze stanem. */
10411
+ /** Semantyka dopasowania siedzi w `@konce-pt/table` — tu zostaje tylko spięcie ze stanem. */
11689
10412
  matchesColumnFilters(row) {
11690
10413
  const filters = this.columnFilters();
11691
10414
  const cells = row;
@@ -11873,7 +10596,7 @@ class KptDataTable {
11873
10596
  '[style.--kpt-thead-offset]': "theadOffset() + 'px'",
11874
10597
  }, template: "@if (filterable() || exportable()) {\n <div class=\"kpt-data-table__toolbar\">\n @if (filterable()) {\n <input\n class=\"kpt-data-table__filter\"\n type=\"search\"\n [attr.placeholder]=\"i18n.t('dataTable.search')\"\n [value]=\"filterText()\"\n (input)=\"onFilter($event)\"\n />\n }\n @if (exportable()) {\n <kpt-button variant=\"outline\" size=\"sm\" (click)=\"exportCsv()\">{{ i18n.t('dataTable.exportCsv') }}</kpt-button>\n }\n </div>\n}\n\n<div class=\"kpt-data-table__scroll\" #scrollEl [style.max-height]=\"scrollHeight()\" (scroll)=\"onScroll($event)\">\n <table\n class=\"kpt-data-table__table\"\n [class.kpt-data-table__table--frozen]=\"hasFrozen()\"\n [class.kpt-data-table__table--virtual]=\"virtualScroll()\"\n >\n <thead #theadEl>\n @if (hasColumnFilters() && filterRowPosition() === 'top') {\n <ng-container [ngTemplateOutlet]=\"filterRowTpl\" />\n }\n <tr>\n @if (hasRowDetail()) {\n <th class=\"kpt-data-table__expander\" [class.kpt-data-table__cell--frozen]=\"hasFrozen()\" [style.left.px]=\"expanderStickyLeft()\"></th>\n }\n @if (selectable() === 'multiple') {\n <th class=\"kpt-data-table__checkbox\" [class.kpt-data-table__cell--frozen]=\"hasFrozen()\" [style.left.px]=\"checkboxStickyLeft()\">\n <input\n type=\"checkbox\"\n [checked]=\"pageAllSelected()\"\n [indeterminate]=\"pageSomeSelected()\"\n (change)=\"toggleAllOnPage()\"\n [attr.aria-label]=\"i18n.t('dataTable.selectAll')\"\n />\n </th>\n } @else if (selectable() === 'single') {\n <th class=\"kpt-data-table__checkbox\" [class.kpt-data-table__cell--frozen]=\"hasFrozen()\" [style.left.px]=\"checkboxStickyLeft()\"></th>\n }\n @for (col of visibleOrderedColumns(); track col.field) {\n <th\n [attr.draggable]=\"isColDraggable(col) ? true : null\"\n [style.width]=\"col.width\"\n [style.left.px]=\"frozenLeft(col.field)\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [class.kpt-data-table__cell--frozen]=\"isFrozen(col.field)\"\n [class.kpt-data-table__th--sortable]=\"col.sortable\"\n [class.kpt-data-table__th--draggable]=\"isColDraggable(col)\"\n [class.kpt-data-table__th--dragover]=\"dragField() !== null && dragField() !== col.field && !col.frozen\"\n [attr.aria-sort]=\"ariaSort(col)\"\n (click)=\"toggleSort(col)\"\n (dragstart)=\"onColDragStart(col.field, $event)\"\n (dragover)=\"reorderable() ? onColDragOver(col.field, $event) : null\"\n (drop)=\"reorderable() ? onColDrop(col.field, $event) : null\"\n (dragend)=\"onColDragEnd()\"\n >\n @if (isColDraggable(col)) {\n <kpt-icon class=\"kpt-data-table__grip\" name=\"grip-vertical\" />\n }\n <span>{{ col.header }}</span>\n @if (col.sortable) {\n <kpt-icon\n class=\"kpt-data-table__sort\"\n [class.kpt-data-table__sort--active]=\"ariaSort(col) !== 'none'\"\n [name]=\"sortIconName(col)\"\n />\n }\n </th>\n }\n </tr>\n @if (hasColumnFilters() && filterRowPosition() === 'bottom') {\n <ng-container [ngTemplateOutlet]=\"filterRowTpl\" />\n }\n </thead>\n <tbody>\n @if (loading()) {\n <tr><td class=\"kpt-data-table__state\" [attr.colspan]=\"colspan()\">{{ i18n.t('dataTable.loading') }}</td></tr>\n } @else if (displayCount() === 0) {\n <tr><td class=\"kpt-data-table__state\" [attr.colspan]=\"colspan()\">{{ emptyText() }}</td></tr>\n } @else if (virtualScroll()) {\n @if (topPad() > 0) {\n <tr class=\"kpt-data-table__spacer\" aria-hidden=\"true\"><td [attr.colspan]=\"colspan()\" [style.height.px]=\"topPad()\"></td></tr>\n }\n @for (row of virtualRows(); track trackRow(row)) {\n <ng-container [ngTemplateOutlet]=\"rowTpl\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n @if (bottomPad() > 0) {\n <tr class=\"kpt-data-table__spacer\" aria-hidden=\"true\"><td [attr.colspan]=\"colspan()\" [style.height.px]=\"bottomPad()\"></td></tr>\n }\n } @else {\n @for (row of paged(); track trackRow(row)) {\n <ng-container [ngTemplateOutlet]=\"rowTpl\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n }\n </tbody>\n @if (hasSummary() && !loading() && displayCount() > 0) {\n <tfoot>\n <tr class=\"kpt-data-table__summary\">\n @if (summaryLabelSpan() > 0) {\n <th\n class=\"kpt-data-table__summary-label\"\n [attr.colspan]=\"summaryLabelSpan()\"\n [class.kpt-data-table__cell--frozen]=\"hasFrozen()\"\n [style.left.px]=\"hasFrozen() ? 0 : null\"\n >\n {{ summaryLabelText() }}\n </th>\n }\n @for (col of visibleOrderedColumns(); track col.field; let i = $index) {\n @if (i >= summaryStartIndex()) {\n <td\n [attr.data-align]=\"col.align ?? 'end'\"\n [style.width]=\"col.width\"\n [style.left.px]=\"frozenLeft(col.field)\"\n [class.kpt-data-table__cell--frozen]=\"isFrozen(col.field)\"\n >\n {{ summaryText(col.field) }}\n </td>\n }\n }\n </tr>\n </tfoot>\n }\n </table>\n</div>\n\n<ng-template #rowTpl let-row>\n <tr\n [class.kpt-data-table__row--selected]=\"isSelected(row)\"\n [class.kpt-data-table__row--expanded]=\"hasRowDetail() && isExpanded(row)\"\n [style.height.px]=\"virtualScroll() ? rowHeight() : null\"\n (click)=\"onRowClick(row)\"\n >\n @if (hasRowDetail()) {\n <td class=\"kpt-data-table__expander\" [class.kpt-data-table__cell--frozen]=\"hasFrozen()\" [style.left.px]=\"expanderStickyLeft()\">\n <button\n type=\"button\"\n class=\"kpt-data-table__expander-btn\"\n [class.kpt-data-table__expander-btn--open]=\"isExpanded(row)\"\n [attr.aria-expanded]=\"isExpanded(row)\"\n [attr.aria-label]=\"i18n.t('dataTable.expandRow')\"\n (click)=\"$event.stopPropagation(); toggleExpand(row)\"\n >\n <kpt-icon name=\"chevron-right\" />\n </button>\n </td>\n }\n @if (selectable() !== 'none') {\n <td class=\"kpt-data-table__checkbox\" [class.kpt-data-table__cell--frozen]=\"hasFrozen()\" [style.left.px]=\"checkboxStickyLeft()\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(row)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRow(row)\"\n [attr.aria-label]=\"i18n.t('dataTable.selectRow')\"\n />\n </td>\n }\n @for (col of visibleOrderedColumns(); track col.field) {\n <td\n [attr.data-align]=\"col.align ?? 'start'\"\n [style.left.px]=\"frozenLeft(col.field)\"\n [class.kpt-data-table__cell--frozen]=\"isFrozen(col.field)\"\n [class.kpt-data-table__cell--editable]=\"isEditable(col) && !isEditingCell(row, col.field)\"\n [attr.tabindex]=\"isEditable(col) && !isEditingCell(row, col.field) ? 0 : null\"\n [attr.aria-label]=\"isEditable(col) && !isEditingCell(row, col.field) ? i18n.t('dataTable.editCell', { column: col.header }) : null\"\n (click)=\"isEditable(col) ? startEdit(row, col, $event) : null\"\n (keydown.enter)=\"isEditable(col) && !isEditingCell(row, col.field) ? startEdit(row, col, $event) : null\"\n >\n @if (isEditingCell(row, col.field)) {\n <div\n class=\"kpt-data-table__editor\"\n #editorHost\n (click)=\"$event.stopPropagation()\"\n (focusout)=\"onEditorFocusOut($event)\"\n >\n @if (cellEditTemplate(col.field); as etpl) {\n <ng-container\n [ngTemplateOutlet]=\"etpl\"\n [ngTemplateOutletContext]=\"{ $implicit: editingValue(), row, commit: commitEditValue, cancel: cancelEdit }\"\n />\n } @else {\n @switch (col.edit?.type) {\n @case ('text') {\n <kpt-input\n [value]=\"$any(editingValue()) ?? ''\"\n [placeholder]=\"col.edit.placeholder ?? ''\"\n (valueChange)=\"editingValue.set($event)\"\n (keydown.enter)=\"commitEdit()\"\n (keydown.escape)=\"cancelEdit()\"\n />\n }\n @case ('number') {\n <kpt-input-number\n [value]=\"$any(editingValue())\"\n [min]=\"col.edit.min\"\n [max]=\"col.edit.max\"\n [step]=\"col.edit.step ?? 1\"\n (valueChange)=\"editingValue.set($event)\"\n (keydown.enter)=\"commitEdit()\"\n (keydown.escape)=\"cancelEdit()\"\n />\n }\n @case ('date') {\n <kpt-datepicker\n [value]=\"$any(editingValue()) ?? ''\"\n (valueChange)=\"editingValue.set($event)\"\n [open]=\"editorPanelOpen()\"\n (openChange)=\"onEditorPanelToggle($event)\"\n />\n }\n @case ('select') {\n <kpt-select\n [options]=\"col.edit.options ?? []\"\n [placeholder]=\"col.edit.placeholder ?? ''\"\n [value]=\"editingValue()\"\n (valueChange)=\"editingValue.set($event)\"\n [open]=\"editorPanelOpen()\"\n (openChange)=\"onEditorPanelToggle($event)\"\n />\n }\n @case ('multiselect') {\n <kpt-select\n multiple\n filter\n [options]=\"col.edit.options ?? []\"\n [placeholder]=\"col.edit.placeholder ?? ''\"\n [value]=\"editingValue()\"\n (valueChange)=\"editingValue.set($event)\"\n [open]=\"editorPanelOpen()\"\n (openChange)=\"onEditorPanelToggle($event)\"\n />\n }\n }\n }\n </div>\n } @else if (cellTemplate(col.field); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row, value: getValue(row, col.field) }\"\n />\n } @else {\n {{ getValue(row, col.field) }}\n }\n </td>\n }\n </tr>\n @if (hasRowDetail() && isExpanded(row) && !virtualScroll()) {\n <tr class=\"kpt-data-table__detail-row\">\n <td class=\"kpt-data-table__detail\" [attr.colspan]=\"colspan()\">\n <ng-container [ngTemplateOutlet]=\"rowDetailTpl()\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </td>\n </tr>\n }\n</ng-template>\n\n<ng-template #filterRowTpl>\n <tr class=\"kpt-data-table__filter-row\">\n @if (hasRowDetail()) {\n <th class=\"kpt-data-table__expander\" [class.kpt-data-table__cell--frozen]=\"hasFrozen()\" [style.left.px]=\"expanderStickyLeft()\"></th>\n }\n @if (selectable() !== 'none') {\n <th class=\"kpt-data-table__checkbox\" [class.kpt-data-table__cell--frozen]=\"hasFrozen()\" [style.left.px]=\"checkboxStickyLeft()\"></th>\n }\n @for (col of visibleOrderedColumns(); track col.field) {\n <th\n [style.width]=\"col.width\"\n [style.left.px]=\"frozenLeft(col.field)\"\n [attr.data-align]=\"col.align ?? 'start'\"\n [class.kpt-data-table__cell--frozen]=\"isFrozen(col.field)\"\n >\n @switch (col.filter?.type) {\n @case ('text') {\n <input\n class=\"kpt-data-table__fcell\"\n type=\"search\"\n [attr.placeholder]=\"col.filter.placeholder || ''\"\n [attr.aria-label]=\"i18n.t('dataTable.filter', { column: col.header })\"\n [value]=\"$any(columnFilters()[col.field]) || ''\"\n (input)=\"setColumnFilter(col.field, $any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n @case ('number') {\n <input\n class=\"kpt-data-table__fcell\"\n type=\"text\"\n inputmode=\"numeric\"\n [attr.placeholder]=\"col.filter.placeholder || ''\"\n [attr.aria-label]=\"i18n.t('dataTable.filter', { column: col.header })\"\n [value]=\"$any(columnFilters()[col.field]) || ''\"\n (input)=\"onNumberFilter(col.field, $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n }\n @case ('select') {\n <kpt-select\n [options]=\"col.filter.options || []\"\n [multiple]=\"!!col.filter.multiple\"\n filter\n [placeholder]=\"col.filter.placeholder || i18n.t('dataTable.all')\"\n [value]=\"columnFilters()[col.field] ?? null\"\n (valueChange)=\"setColumnFilter(col.field, $event)\"\n />\n }\n @case ('numberRange') {\n <div class=\"kpt-data-table__frange\">\n <input\n class=\"kpt-data-table__fcell\"\n type=\"text\"\n inputmode=\"numeric\"\n [attr.placeholder]=\"i18n.t('dataTable.min')\"\n [attr.aria-label]=\"i18n.t('dataTable.filterMin', { column: col.header })\"\n [value]=\"rangeVal(col.field).min\"\n (input)=\"setRangeFilter(col.field, 'min', $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n <input\n class=\"kpt-data-table__fcell\"\n type=\"text\"\n inputmode=\"numeric\"\n [attr.placeholder]=\"i18n.t('dataTable.max')\"\n [attr.aria-label]=\"i18n.t('dataTable.filterMax', { column: col.header })\"\n [value]=\"rangeVal(col.field).max\"\n (input)=\"setRangeFilter(col.field, 'max', $event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n @case ('slider') {\n <div class=\"kpt-data-table__fslider\" (click)=\"$event.stopPropagation()\">\n <kpt-slider\n range\n [min]=\"col.filter.min ?? 0\"\n [max]=\"col.filter.max ?? 100\"\n [step]=\"col.filter.step ?? 1\"\n [value]=\"sliderVal(col)\"\n (valueChange)=\"setColumnFilter(col.field, $event)\"\n showValue\n />\n </div>\n }\n @case ('dateRange') {\n <kpt-date-range\n [placeholder]=\"col.filter.placeholder || i18n.t('dataTable.dateRange')\"\n [value]=\"$any(columnFilters()[col.field]) || { start: '', end: '' }\"\n (valueChange)=\"setColumnFilter(col.field, $event)\"\n />\n }\n }\n </th>\n }\n </tr>\n</ng-template>\n\n@if (pageSize() > 0 && !virtualScroll()) {\n <div class=\"kpt-data-table__pager\">\n <ng-content select=\"[kptPaginatorActions]\" />\n <kpt-paginator\n [length]=\"filteredCount()\"\n [pageIndex]=\"pageIndex()\"\n (pageIndexChange)=\"pageIndex.set($event)\"\n [pageSize]=\"pageSizeState()\"\n (pageSizeChange)=\"pageSizeState.set($event)\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n />\n </div>\n}\n", styles: ["@layer kpt.components{.kpt-data-table{display:flex;flex-direction:column;background:var(--kpt-table-bg);color:var(--kpt-table-fg);border:var(--kpt-border-width-thin, 1px) solid var(--kpt-table-border);border-radius:var(--kpt-table-radius, .75rem);overflow:hidden;flex-grow:1}.kpt-data-table__toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--kpt-space-3, .75rem);padding:var(--kpt-space-3, .75rem);border-bottom:var(--kpt-border-width-thin, 1px) solid var(--kpt-table-border)}.kpt-data-table__filter{width:100%;max-width:20rem;height:2.25rem;padding-inline:var(--kpt-space-3, .75rem);border:var(--kpt-border-width-thin, 1px) solid var(--kpt-form-field-border);border-radius:var(--kpt-form-field-radius, .5rem);background:var(--kpt-form-field-bg);color:var(--kpt-form-field-text)}.kpt-data-table__filter:focus-visible{outline:none;border-color:var(--kpt-form-field-border-focus);box-shadow:0 0 0 2px color-mix(in oklch,var(--kpt-form-field-border-focus) 30%,transparent)}.kpt-data-table__scroll{overflow:auto}.kpt-data-table__pager{display:flex;align-items:center;gap:var(--kpt-space-2, .5rem)}.kpt-data-table__pager [kptPaginatorActions]{margin-inline-start:.5rem}.kpt-data-table__pager kpt-paginator{flex:1 1 auto;min-width:0}.kpt-data-table__table{width:100%;border-collapse:collapse;font-size:var(--kpt-font-size-sm, .875rem)}.kpt-data-table__table--frozen{width:max-content;min-width:100%}.kpt-data-table__table th,.kpt-data-table__table td{padding:var(--kpt-table-cell-padding, .75rem);text-align:start;border-bottom:var(--kpt-border-width-thin, 1px) solid var(--kpt-table-border)}.kpt-data-table__table th[data-align=center],.kpt-data-table__table td[data-align=center]{text-align:center}.kpt-data-table__table th[data-align=end],.kpt-data-table__table td[data-align=end]{text-align:end}.kpt-data-table__table thead th{position:sticky;top:0;z-index:1;background:var(--kpt-table-header-bg);color:var(--kpt-table-header-fg);font-weight:var(--kpt-font-weight-semibold, 600);white-space:nowrap;-webkit-user-select:none;user-select:none}.kpt-data-table__table thead tr:nth-child(2) th{top:var(--kpt-thead-offset, 0px)}.kpt-data-table__table tfoot th,.kpt-data-table__table tfoot td{position:sticky;bottom:0;z-index:1;background:var(--kpt-table-summary-bg, var(--kpt-table-header-bg));color:var(--kpt-table-header-fg);font-weight:var(--kpt-font-weight-semibold, 600);white-space:nowrap;border-bottom:0;border-top:var(--kpt-border-width-thin, 1px) solid var(--kpt-table-border)}.kpt-data-table__table .kpt-data-table__summary-label{text-align:end}.kpt-data-table__filter-row th{padding:var(--kpt-space-2, .5rem);font-weight:var(--kpt-font-weight-normal, 400);cursor:auto}.kpt-data-table__fcell{width:100%;height:2rem;padding-inline:var(--kpt-space-2, .5rem);border:var(--kpt-border-width-thin, 1px) solid var(--kpt-form-field-border);border-radius:var(--kpt-form-field-radius, .5rem);background:var(--kpt-form-field-bg);color:var(--kpt-form-field-text);font:inherit}.kpt-data-table__fcell:focus-visible{outline:none;border-color:var(--kpt-form-field-border-focus);box-shadow:0 0 0 2px color-mix(in oklch,var(--kpt-form-field-border-focus) 30%,transparent)}.kpt-data-table__filter-row kpt-select,.kpt-data-table__filter-row kpt-date-range{display:block;width:100%;font-weight:var(--kpt-font-weight-normal, 400)}.kpt-data-table__frange{display:flex;gap:var(--kpt-space-2, .5rem)}.kpt-data-table__frange .kpt-data-table__fcell{min-width:0}.kpt-data-table__fslider .kpt-slider-host{width:100%}.kpt-data-table__fslider .kpt-slider__value{min-width:auto;font-size:var(--kpt-font-size-xs, .75rem);color:var(--kpt-color-on-surface-muted)}.kpt-data-table__th--sortable{cursor:pointer}.kpt-data-table__th--sortable:hover{color:var(--kpt-color-on-surface)}.kpt-data-table__cell--editable{cursor:pointer}.kpt-data-table__cell--editable:hover{background:var(--kpt-table-row-hover)}.kpt-data-table__cell--editable:focus-visible{outline:var(--kpt-border-width-medium, 2px) solid var(--kpt-color-focus-ring);outline-offset:-2px}.kpt-data-table__editor{display:block;min-width:8rem}.kpt-data-table__editor .kpt-input-number-host{max-width:6.5rem}.kpt-data-table__editor .kpt-input-number__btn{width:1.75rem}.kpt-data-table__sort{margin-inline-start:.35em;opacity:.35}.kpt-data-table__sort--active{opacity:1}.kpt-data-table__th--draggable{cursor:grab}.kpt-data-table__th--draggable:active{cursor:grabbing}.kpt-data-table__th--dragover{box-shadow:inset 2px 0 0 0 var(--kpt-color-primary)}.kpt-data-table__grip{margin-inline-end:.4em;opacity:.45}.kpt-data-table__checkbox{width:1px;white-space:nowrap;text-align:center}.kpt-data-table__checkbox input[type=checkbox]{appearance:none;-webkit-appearance:none;position:relative;display:inline-block;width:1.15rem;height:1.15rem;margin:0;vertical-align:middle;cursor:pointer;border:var(--kpt-border-width-medium, 2px) solid var(--kpt-form-field-border);border-radius:var(--kpt-radius-sm, .25rem);background:var(--kpt-form-field-bg);transition:background-color var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard),border-color var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard)}.kpt-data-table__checkbox input[type=checkbox]:after{content:\"\";position:absolute;inset:0;opacity:0;background-color:var(--kpt-color-on-primary);transition:opacity var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard);-webkit-mask:no-repeat center/.85rem;mask:no-repeat center/.85rem}.kpt-data-table__checkbox input[type=checkbox]:checked,.kpt-data-table__checkbox input[type=checkbox]:indeterminate{background:var(--kpt-color-primary);border-color:var(--kpt-color-primary)}.kpt-data-table__checkbox input[type=checkbox]:checked:after{opacity:1;-webkit-mask-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M13 4.5 6.5 11 3 7.5' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M13 4.5 6.5 11 3 7.5' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\")}.kpt-data-table__checkbox input[type=checkbox]:indeterminate:after{opacity:1;-webkit-mask-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8h9' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round'/%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8h9' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round'/%3E%3C/svg%3E\")}.kpt-data-table__checkbox input[type=checkbox]:focus-visible{outline:var(--kpt-border-width-medium, 2px) solid var(--kpt-color-focus-ring);outline-offset:2px}.kpt-data-table__expander{width:2.5rem;min-width:2.5rem;text-align:center;white-space:nowrap}.kpt-data-table__expander-btn{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0;border:none;border-radius:var(--kpt-radius-sm, .25rem);background:transparent;color:var(--kpt-color-on-surface-muted);cursor:pointer;transition:background-color var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard),color var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard)}.kpt-data-table__expander-btn kpt-icon{display:inline-flex;transition:transform var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard)}.kpt-data-table__expander-btn:hover{background:var(--kpt-table-row-hover);color:var(--kpt-color-on-surface)}.kpt-data-table__expander-btn:focus-visible{outline:var(--kpt-border-width-medium, 2px) solid var(--kpt-color-focus-ring);outline-offset:2px}.kpt-data-table__expander-btn--open{color:var(--kpt-color-primary)}.kpt-data-table__expander-btn--open kpt-icon{transform:rotate(90deg)}.kpt-data-table__detail-row>.kpt-data-table__detail{padding:var(--kpt-space-4, 1rem);background:var(--kpt-table-detail-bg, var(--kpt-color-surface-variant, var(--kpt-table-row-hover)));border-bottom:var(--kpt-border-width-thin, 1px) solid var(--kpt-table-border);box-shadow:inset 3px 0 0 0 var(--kpt-color-primary)}.kpt-data-table tbody tr{transition:background-color var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard)}.kpt-data-table tbody tr:hover{background:var(--kpt-table-row-hover)}.kpt-data-table tbody tr.kpt-data-table__detail-row:hover{background:transparent}.kpt-data-table__row--selected{background:var(--kpt-table-row-selected)!important}.kpt-data-table__row--expanded{background:var(--kpt-table-row-hover)}.kpt-data-table__table--frozen .kpt-data-table__checkbox{width:3rem;min-width:3rem}.kpt-data-table__table--frozen .kpt-data-table__expander{width:2.5rem;min-width:2.5rem}.kpt-data-table__cell--frozen{position:sticky;z-index:1;background:var(--kpt-table-bg);border-inline-end:var(--kpt-border-width-thin, 1px) solid var(--kpt-table-border)}.kpt-data-table thead th.kpt-data-table__cell--frozen{z-index:3;background:var(--kpt-table-header-bg)}.kpt-data-table tfoot th.kpt-data-table__cell--frozen,.kpt-data-table tfoot td.kpt-data-table__cell--frozen{z-index:3;background:var(--kpt-table-summary-bg, var(--kpt-table-header-bg))}.kpt-data-table tbody tr:hover .kpt-data-table__cell--frozen{background:var(--kpt-table-row-hover)}.kpt-data-table__row--selected.kpt-data-table__row--selected .kpt-data-table__cell--frozen,.kpt-data-table tbody tr.kpt-data-table__row--selected .kpt-data-table__cell--frozen{background:var(--kpt-table-row-selected)}.kpt-data-table__state{padding:var(--kpt-space-8, 2rem)!important;text-align:center!important;color:var(--kpt-color-on-surface-muted)}.kpt-data-table__table--virtual td{padding-block:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.kpt-data-table__spacer td{padding:0!important;border:0!important}.kpt-data-table tbody tr:last-child td{border-bottom:0}}\n"] }]
11875
10598
  }], () => [], { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], filterRowPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterRowPosition", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], exportFilename: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportFilename", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], multiExpand: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiExpand", required: false }] }], summaryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryLabel", required: false }] }], summaryValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryValues", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], expandedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedRows", required: false }] }, { type: i0.Output, args: ["expandedRowsChange"] }], hiddenFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenFields", required: false }] }, { type: i0.Output, args: ["hiddenFieldsChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], scrollEl: [{ type: i0.ViewChild, args: ['scrollEl', { isSignal: true }] }], theadEl: [{ type: i0.ViewChild, args: ['theadEl', { isSignal: true }] }], editorHost: [{ type: i0.ViewChild, args: ['editorHost', { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => KptCellDef), { isSignal: true }] }], cellEditDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => KptCellEditDef), { isSignal: true }] }], rowDetailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KptRowDetailDef), { isSignal: true }] }] }); })();
11876
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptDataTable, { className: "KptDataTable", filePath: "lib/data-table/data-table.component.ts", lineNumber: 157 }); })();
10599
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptDataTable, { className: "KptDataTable", filePath: "lib/data-table/data-table.component.ts", lineNumber: 163 }); })();
11877
10600
 
11878
10601
  const _c0$c = a0 => ({ $implicit: a0, level: 0 });
11879
10602
  const _c1$4 = (a0, a1) => ({ $implicit: a0, level: a1 });
@@ -11886,7 +10609,7 @@ function KptTree_ng_template_2_For_1_Conditional_2_Template(rf, ctx) { if (rf &
11886
10609
  } if (rf & 2) {
11887
10610
  const node_r2 = i0.ɵɵnextContext().$implicit;
11888
10611
  const ctx_r2 = i0.ɵɵnextContext(2);
11889
- i0.ɵɵattribute("aria-label", ctx_r2.isOpen(node_r2) ? "Zwi\u0144" : "Rozwi\u0144");
10612
+ i0.ɵɵattribute("aria-label", ctx_r2.isOpen(node_r2) ? ctx_r2.i18n.t("tree.collapse") : ctx_r2.i18n.t("tree.expand"));
11890
10613
  i0.ɵɵadvance();
11891
10614
  i0.ɵɵclassProp("is-open", ctx_r2.isOpen(node_r2));
11892
10615
  } }
@@ -11959,6 +10682,7 @@ class KptTree {
11959
10682
  this.selected = model(null, /* @ts-ignore */
11960
10683
  ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
11961
10684
  this.nodeClick = output();
10685
+ this.i18n = inject(KptI18n);
11962
10686
  this.version = signal(0, /* @ts-ignore */
11963
10687
  ...(ngDevMode ? [{ debugName: "version" }] : /* istanbul ignore next */ []));
11964
10688
  }
@@ -12018,7 +10742,7 @@ class KptTree {
12018
10742
  (click)="onRow(node)"
12019
10743
  >
12020
10744
  @if (has(node)) {
12021
- <button type="button" class="kpt-tree__toggle" (click)="toggle(node, $event)" [attr.aria-label]="isOpen(node) ? 'Zwiń' : 'Rozwiń'">
10745
+ <button type="button" class="kpt-tree__toggle" (click)="toggle(node, $event)" [attr.aria-label]="isOpen(node) ? i18n.t('tree.collapse') : i18n.t('tree.expand')">
12022
10746
  <kpt-icon name="chevron-right" class="kpt-tree__chevron" [class.is-open]="isOpen(node)" />
12023
10747
  </button>
12024
10748
  } @else {
@@ -12037,7 +10761,7 @@ class KptTree {
12037
10761
  </ng-template>
12038
10762
  `, host: { class: 'kpt-tree-host' }, styles: ["@layer kpt.components{.kpt-tree-host{display:block}.kpt-tree,.kpt-tree ul{list-style:none;margin:0;padding:0}.kpt-tree__row{display:flex;align-items:center;gap:.35rem;padding-block:.3rem;padding-inline-end:.5rem;border-radius:var(--kpt-radius-sm, .25rem);cursor:pointer;font-size:var(--kpt-font-size-sm, .875rem);color:var(--kpt-color-on-surface)}.kpt-tree__row:hover{background:var(--kpt-color-surface-variant)}.kpt-tree__row.is-selected{background:color-mix(in oklch,var(--kpt-color-primary) 14%,var(--kpt-color-surface));color:var(--kpt-color-primary)}.kpt-tree__row.is-disabled{opacity:.5;cursor:not-allowed}.kpt-tree__toggle{display:inline-flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;flex-shrink:0;border:0;background:none;cursor:pointer;color:var(--kpt-color-on-surface-muted);padding:0}.kpt-tree__spacer{display:inline-block;width:1.25rem;flex-shrink:0}.kpt-tree__chevron{transition:transform var(--kpt-motion-duration-fast, .12s) var(--kpt-motion-easing-standard)}.kpt-tree__chevron.is-open{transform:rotate(90deg)}.kpt-tree__icon{color:var(--kpt-color-on-surface-muted)}.kpt-tree__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}\n"] }]
12039
10763
  }], null, { nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], nodeClick: [{ type: i0.Output, args: ["nodeClick"] }] }); })();
12040
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptTree, { className: "KptTree", filePath: "lib/tree/tree.component.ts", lineNumber: 62 }); })();
10764
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KptTree, { className: "KptTree", filePath: "lib/tree/tree.component.ts", lineNumber: 63 }); })();
12041
10765
 
12042
10766
  function KptTimeline_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
12043
10767
  i0.ɵɵelement(0, "kpt-icon", 3);
@@ -14503,5 +13227,5 @@ class KptSpeedDial {
14503
13227
  * Generated bundle index. Do not edit.
14504
13228
  */
14505
13229
 
14506
- export { KPT_BREAKPOINTS, KPT_FORM_FIELD_CONTROL, KPT_I18N_CONFIG, KPT_MESSAGES_EN, KPT_MESSAGES_PL, KptAccordion, KptAccordionPanel, KptAlert, KptAppShell, KptAuth, KptAuthProviderDef, KptAutocomplete, KptAvatar, KptAvatarGroup, KptBadge, KptBottomSheet, KptBreadcrumb, KptBreakpointObserver, KptButton, KptButtonGroup, KptCard, KptCarousel, KptCellDef, KptCellEditDef, KptCheckbox, KptChip, KptChipsInput, KptClock, KptColorPicker, KptConfirmContainer, KptConfirmService, KptContextMenu, KptDataTable, KptDataView, KptDateRange, KptDatepicker, KptDialog, KptDivider, KptDrawer, KptEmpty, KptFab, KptFieldset, KptFileUpload, KptFormField, KptGalleria, KptI18n, KptIcon, KptIconButton, KptIconRegistry, KptImage, KptInput, KptInputMask, KptInputNumber, KptInputOtp, KptKnob, KptListbox, KptMegamenu, KptMenu, KptMenubar, KptMeterGroup, KptOrderList, KptPaginator, KptPanel, KptPassword, KptPickList, KptPopover, KptProgress, KptRadioGroup, KptRating, KptRichText, KptRowDetailDef, KptScrollTop, KptSelect, KptShellNavToggle, KptSidenav, KptSkeleton, KptSlider, KptSpeedDial, KptSpinner, KptSplitButton, KptSplitter, KptStep, KptStepper, KptSwitch, KptSwitchGroup, KptTab, KptTabs, KptTextarea, KptTimeline, KptToastContainer, KptToastService, KptToolbar, KptTooltip, KptTree, provideKptI18n, renderKptIconSvg };
13230
+ export { KPT_BREAKPOINTS, KPT_FORM_FIELD_CONTROL, KPT_I18N_CONFIG, KptAccordion, KptAccordionPanel, KptAlert, KptAppShell, KptAuth, KptAuthProviderDef, KptAutocomplete, KptAvatar, KptAvatarGroup, KptBadge, KptBottomSheet, KptBreadcrumb, KptBreakpointObserver, KptButton, KptButtonGroup, KptCard, KptCarousel, KptCellDef, KptCellEditDef, KptCheckbox, KptChip, KptChipsInput, KptClock, KptColorPicker, KptConfirmContainer, KptConfirmService, KptContextMenu, KptDataTable, KptDataView, KptDateRange, KptDatepicker, KptDialog, KptDivider, KptDrawer, KptEmpty, KptFab, KptFieldset, KptFileUpload, KptFormField, KptGalleria, KptI18n, KptIcon, KptIconButton, KptIconRegistry, KptImage, KptInput, KptInputMask, KptInputNumber, KptInputOtp, KptKnob, KptListbox, KptMegamenu, KptMenu, KptMenubar, KptMeterGroup, KptOrderList, KptPaginator, KptPanel, KptPassword, KptPickList, KptPopover, KptProgress, KptRadioGroup, KptRating, KptRichText, KptRowDetailDef, KptScrollTop, KptSelect, KptShellNavToggle, KptSidenav, KptSkeleton, KptSlider, KptSpeedDial, KptSpinner, KptSplitButton, KptSplitter, KptStep, KptStepper, KptSwitch, KptSwitchGroup, KptTab, KptTabs, KptTextarea, KptTimeline, KptToastContainer, KptToastService, KptToolbar, KptTooltip, KptTree, provideKptI18n };
14507
13231
  //# sourceMappingURL=konce-pt-angular.mjs.map