@mesgflow/ui-kit 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +200 -0
- package/fesm2022/mesgflow-ui-kit-accordion.mjs +75 -0
- package/fesm2022/mesgflow-ui-kit-accordion.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-alert.mjs +165 -0
- package/fesm2022/mesgflow-ui-kit-alert.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-avatar-group.mjs +88 -0
- package/fesm2022/mesgflow-ui-kit-avatar-group.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-avatar.mjs +123 -0
- package/fesm2022/mesgflow-ui-kit-avatar.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-badge.mjs +68 -0
- package/fesm2022/mesgflow-ui-kit-badge.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-banner.mjs +111 -0
- package/fesm2022/mesgflow-ui-kit-banner.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-box-input.mjs +78 -0
- package/fesm2022/mesgflow-ui-kit-box-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-brand.mjs +120 -0
- package/fesm2022/mesgflow-ui-kit-brand.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-breadcrumb.mjs +84 -0
- package/fesm2022/mesgflow-ui-kit-breadcrumb.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-button-group.mjs +37 -0
- package/fesm2022/mesgflow-ui-kit-button-group.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-button.mjs +359 -0
- package/fesm2022/mesgflow-ui-kit-button.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-card.mjs +128 -0
- package/fesm2022/mesgflow-ui-kit-card.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-chart.mjs +538 -0
- package/fesm2022/mesgflow-ui-kit-chart.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs +45 -0
- package/fesm2022/mesgflow-ui-kit-checkbox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-chip.mjs +123 -0
- package/fesm2022/mesgflow-ui-kit-chip.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-code-block.mjs +71 -0
- package/fesm2022/mesgflow-ui-kit-code-block.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-collapsible.mjs +89 -0
- package/fesm2022/mesgflow-ui-kit-collapsible.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs +210 -0
- package/fesm2022/mesgflow-ui-kit-color-picker.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-combobox.mjs +181 -0
- package/fesm2022/mesgflow-ui-kit-combobox.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-command.mjs +491 -0
- package/fesm2022/mesgflow-ui-kit-command.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs +92 -0
- package/fesm2022/mesgflow-ui-kit-context-menu.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-copy-button.mjs +167 -0
- package/fesm2022/mesgflow-ui-kit-copy-button.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-core.mjs +624 -0
- package/fesm2022/mesgflow-ui-kit-core.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs +643 -0
- package/fesm2022/mesgflow-ui-kit-date-picker.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-description-list.mjs +76 -0
- package/fesm2022/mesgflow-ui-kit-description-list.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-dialog.mjs +700 -0
- package/fesm2022/mesgflow-ui-kit-dialog.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-divider.mjs +62 -0
- package/fesm2022/mesgflow-ui-kit-divider.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs +126 -0
- package/fesm2022/mesgflow-ui-kit-dropzone.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-empty-state.mjs +70 -0
- package/fesm2022/mesgflow-ui-kit-empty-state.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-field.mjs +42 -0
- package/fesm2022/mesgflow-ui-kit-field.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-hover-card.mjs +171 -0
- package/fesm2022/mesgflow-ui-kit-hover-card.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs +258 -0
- package/fesm2022/mesgflow-ui-kit-i18n-tr.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-icon.mjs +174 -0
- package/fesm2022/mesgflow-ui-kit-icon.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-input.mjs +448 -0
- package/fesm2022/mesgflow-ui-kit-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-kbd.mjs +24 -0
- package/fesm2022/mesgflow-ui-kit-kbd.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-link.mjs +48 -0
- package/fesm2022/mesgflow-ui-kit-link.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-menu.mjs +105 -0
- package/fesm2022/mesgflow-ui-kit-menu.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-number-input.mjs +153 -0
- package/fesm2022/mesgflow-ui-kit-number-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-otp-input.mjs +164 -0
- package/fesm2022/mesgflow-ui-kit-otp-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-page-header.mjs +83 -0
- package/fesm2022/mesgflow-ui-kit-page-header.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-pagination.mjs +99 -0
- package/fesm2022/mesgflow-ui-kit-pagination.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-password-input.mjs +120 -0
- package/fesm2022/mesgflow-ui-kit-password-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-popover.mjs +213 -0
- package/fesm2022/mesgflow-ui-kit-popover.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-progress.mjs +82 -0
- package/fesm2022/mesgflow-ui-kit-progress.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-radio.mjs +123 -0
- package/fesm2022/mesgflow-ui-kit-radio.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-rating.mjs +116 -0
- package/fesm2022/mesgflow-ui-kit-rating.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-scroll-area.mjs +84 -0
- package/fesm2022/mesgflow-ui-kit-scroll-area.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-search-input.mjs +154 -0
- package/fesm2022/mesgflow-ui-kit-search-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs +95 -0
- package/fesm2022/mesgflow-ui-kit-segmented-control.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-select.mjs +227 -0
- package/fesm2022/mesgflow-ui-kit-select.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs +449 -0
- package/fesm2022/mesgflow-ui-kit-sidebar.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs +74 -0
- package/fesm2022/mesgflow-ui-kit-skeleton.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-slider.mjs +179 -0
- package/fesm2022/mesgflow-ui-kit-slider.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-spinner.mjs +67 -0
- package/fesm2022/mesgflow-ui-kit-spinner.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-splitter.mjs +97 -0
- package/fesm2022/mesgflow-ui-kit-splitter.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs +98 -0
- package/fesm2022/mesgflow-ui-kit-stat-tile.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-stepper.mjs +133 -0
- package/fesm2022/mesgflow-ui-kit-stepper.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-switch.mjs +73 -0
- package/fesm2022/mesgflow-ui-kit-switch.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-table.mjs +1783 -0
- package/fesm2022/mesgflow-ui-kit-table.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tabs.mjs +569 -0
- package/fesm2022/mesgflow-ui-kit-tabs.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs +138 -0
- package/fesm2022/mesgflow-ui-kit-tag-input.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-theme-switcher.mjs +53 -0
- package/fesm2022/mesgflow-ui-kit-theme-switcher.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-theming.mjs +1016 -0
- package/fesm2022/mesgflow-ui-kit-theming.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs +138 -0
- package/fesm2022/mesgflow-ui-kit-time-picker.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-timeline.mjs +91 -0
- package/fesm2022/mesgflow-ui-kit-timeline.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-toast.mjs +202 -0
- package/fesm2022/mesgflow-ui-kit-toast.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-toggle.mjs +243 -0
- package/fesm2022/mesgflow-ui-kit-toggle.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs +99 -0
- package/fesm2022/mesgflow-ui-kit-toolbar.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs +160 -0
- package/fesm2022/mesgflow-ui-kit-tooltip.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tour.mjs +272 -0
- package/fesm2022/mesgflow-ui-kit-tour.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tree-select.mjs +177 -0
- package/fesm2022/mesgflow-ui-kit-tree-select.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit-tree.mjs +82 -0
- package/fesm2022/mesgflow-ui-kit-tree.mjs.map +1 -0
- package/fesm2022/mesgflow-ui-kit.mjs +12851 -0
- package/fesm2022/mesgflow-ui-kit.mjs.map +1 -0
- package/package.json +374 -0
- package/preset.css +20 -0
- package/tokens/color.css +693 -0
- package/tokens/contrast.css +68 -0
- package/tokens/elevation.css +68 -0
- package/tokens/motion.css +277 -0
- package/tokens/radius.css +69 -0
- package/tokens/typography.css +127 -0
- package/tokens.css +41 -0
- package/types/mesgflow-ui-kit-accordion.d.ts +42 -0
- package/types/mesgflow-ui-kit-alert.d.ts +60 -0
- package/types/mesgflow-ui-kit-avatar-group.d.ts +28 -0
- package/types/mesgflow-ui-kit-avatar.d.ts +23 -0
- package/types/mesgflow-ui-kit-badge.d.ts +39 -0
- package/types/mesgflow-ui-kit-banner.d.ts +42 -0
- package/types/mesgflow-ui-kit-box-input.d.ts +45 -0
- package/types/mesgflow-ui-kit-brand.d.ts +48 -0
- package/types/mesgflow-ui-kit-breadcrumb.d.ts +26 -0
- package/types/mesgflow-ui-kit-button-group.d.ts +17 -0
- package/types/mesgflow-ui-kit-button.d.ts +75 -0
- package/types/mesgflow-ui-kit-card.d.ts +71 -0
- package/types/mesgflow-ui-kit-chart.d.ts +242 -0
- package/types/mesgflow-ui-kit-checkbox.d.ts +17 -0
- package/types/mesgflow-ui-kit-chip.d.ts +46 -0
- package/types/mesgflow-ui-kit-code-block.d.ts +56 -0
- package/types/mesgflow-ui-kit-collapsible.d.ts +39 -0
- package/types/mesgflow-ui-kit-color-picker.d.ts +78 -0
- package/types/mesgflow-ui-kit-combobox.d.ts +74 -0
- package/types/mesgflow-ui-kit-command.d.ts +185 -0
- package/types/mesgflow-ui-kit-context-menu.d.ts +40 -0
- package/types/mesgflow-ui-kit-copy-button.d.ts +47 -0
- package/types/mesgflow-ui-kit-core.d.ts +508 -0
- package/types/mesgflow-ui-kit-date-picker.d.ts +215 -0
- package/types/mesgflow-ui-kit-description-list.d.ts +23 -0
- package/types/mesgflow-ui-kit-dialog.d.ts +342 -0
- package/types/mesgflow-ui-kit-divider.d.ts +23 -0
- package/types/mesgflow-ui-kit-dropzone.d.ts +47 -0
- package/types/mesgflow-ui-kit-empty-state.d.ts +18 -0
- package/types/mesgflow-ui-kit-field.d.ts +26 -0
- package/types/mesgflow-ui-kit-hover-card.d.ts +52 -0
- package/types/mesgflow-ui-kit-i18n-tr.d.ts +14 -0
- package/types/mesgflow-ui-kit-icon.d.ts +76 -0
- package/types/mesgflow-ui-kit-input.d.ts +186 -0
- package/types/mesgflow-ui-kit-kbd.d.ts +9 -0
- package/types/mesgflow-ui-kit-link.d.ts +20 -0
- package/types/mesgflow-ui-kit-menu.d.ts +53 -0
- package/types/mesgflow-ui-kit-number-input.d.ts +55 -0
- package/types/mesgflow-ui-kit-otp-input.d.ts +44 -0
- package/types/mesgflow-ui-kit-page-header.d.ts +31 -0
- package/types/mesgflow-ui-kit-pagination.d.ts +50 -0
- package/types/mesgflow-ui-kit-password-input.d.ts +33 -0
- package/types/mesgflow-ui-kit-popover.d.ts +62 -0
- package/types/mesgflow-ui-kit-progress.d.ts +32 -0
- package/types/mesgflow-ui-kit-radio.d.ts +59 -0
- package/types/mesgflow-ui-kit-rating.d.ts +56 -0
- package/types/mesgflow-ui-kit-scroll-area.d.ts +27 -0
- package/types/mesgflow-ui-kit-search-input.d.ts +72 -0
- package/types/mesgflow-ui-kit-segmented-control.d.ts +54 -0
- package/types/mesgflow-ui-kit-select.d.ts +89 -0
- package/types/mesgflow-ui-kit-sidebar.d.ts +224 -0
- package/types/mesgflow-ui-kit-skeleton.d.ts +29 -0
- package/types/mesgflow-ui-kit-slider.d.ts +40 -0
- package/types/mesgflow-ui-kit-spinner.d.ts +31 -0
- package/types/mesgflow-ui-kit-splitter.d.ts +40 -0
- package/types/mesgflow-ui-kit-stat-tile.d.ts +54 -0
- package/types/mesgflow-ui-kit-stepper.d.ts +48 -0
- package/types/mesgflow-ui-kit-switch.d.ts +34 -0
- package/types/mesgflow-ui-kit-table.d.ts +805 -0
- package/types/mesgflow-ui-kit-tabs.d.ts +269 -0
- package/types/mesgflow-ui-kit-tag-input.d.ts +33 -0
- package/types/mesgflow-ui-kit-theme-switcher.d.ts +27 -0
- package/types/mesgflow-ui-kit-theming.d.ts +745 -0
- package/types/mesgflow-ui-kit-time-picker.d.ts +54 -0
- package/types/mesgflow-ui-kit-timeline.d.ts +27 -0
- package/types/mesgflow-ui-kit-toast.d.ts +94 -0
- package/types/mesgflow-ui-kit-toggle.d.ts +110 -0
- package/types/mesgflow-ui-kit-toolbar.d.ts +52 -0
- package/types/mesgflow-ui-kit-tooltip.d.ts +55 -0
- package/types/mesgflow-ui-kit-tour.d.ts +66 -0
- package/types/mesgflow-ui-kit-tree-select.d.ts +65 -0
- package/types/mesgflow-ui-kit-tree.d.ts +44 -0
- package/types/mesgflow-ui-kit.d.ts +5444 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, computed, Directive } from '@angular/core';
|
|
3
|
+
import { cn } from '@mesgflow/ui-kit/core';
|
|
4
|
+
|
|
5
|
+
const TONE_CLASSES = {
|
|
6
|
+
neutral: 'text-fg-muted hover:text-fg',
|
|
7
|
+
primary: 'text-accent hover:text-accent-strong',
|
|
8
|
+
success: 'text-success',
|
|
9
|
+
warning: 'text-warning',
|
|
10
|
+
danger: 'text-danger',
|
|
11
|
+
info: 'text-info',
|
|
12
|
+
help: 'text-help',
|
|
13
|
+
};
|
|
14
|
+
const UNDERLINE_CLASSES = {
|
|
15
|
+
always: 'underline underline-offset-2',
|
|
16
|
+
hover: 'no-underline underline-offset-2 hover:underline',
|
|
17
|
+
none: 'no-underline',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* `<a mfLink href="/ayarlar">Ayarlar</a>` — düz metin içine gömülü bağlantılar
|
|
21
|
+
* için (ör. "Zaten hesabınız var mı? Giriş yapın"). Navigasyon bağlantıları
|
|
22
|
+
* (sidebar, tabs, breadcrumb) KENDİ bileşenlerinin stilini taşır, bu
|
|
23
|
+
* directive'i KULLANMAZ — `Link` SADECE metin akışı içindeki bağlantılar için.
|
|
24
|
+
*/
|
|
25
|
+
class Link {
|
|
26
|
+
tone = input('primary', /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
|
|
28
|
+
underline = input('hover', /* @ts-ignore */
|
|
29
|
+
...(ngDevMode ? [{ debugName: "underline" }] : /* istanbul ignore next */ []));
|
|
30
|
+
classes = computed(() => cn('transition-colors duration-fast ease-emphasis focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring', TONE_CLASSES[this.tone()], UNDERLINE_CLASSES[this.underline()]), /* @ts-ignore */
|
|
31
|
+
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
32
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Link, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
33
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: Link, isStandalone: true, selector: "a[mfLink]", inputs: { tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, underline: { classPropertyName: "underline", publicName: "underline", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0 });
|
|
34
|
+
}
|
|
35
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Link, decorators: [{
|
|
36
|
+
type: Directive,
|
|
37
|
+
args: [{
|
|
38
|
+
selector: 'a[mfLink]',
|
|
39
|
+
host: { '[class]': 'classes()' },
|
|
40
|
+
}]
|
|
41
|
+
}], propDecorators: { tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], underline: [{ type: i0.Input, args: [{ isSignal: true, alias: "underline", required: false }] }] } });
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Generated bundle index. Do not edit.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
export { Link };
|
|
48
|
+
//# sourceMappingURL=mesgflow-ui-kit-link.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-link.mjs","sources":["../../../projects/ui-kit/link/link.ts","../../../projects/ui-kit/link/mesgflow-ui-kit-link.ts"],"sourcesContent":["import { Directive, computed, input } from '@angular/core';\r\nimport { cn, type MfTone } from '@mesgflow/ui-kit/core';\r\n\r\nexport type LinkUnderline = 'always' | 'hover' | 'none';\r\n\r\nconst TONE_CLASSES: Record<MfTone, string> = {\r\n neutral: 'text-fg-muted hover:text-fg',\r\n primary: 'text-accent hover:text-accent-strong',\r\n success: 'text-success',\r\n warning: 'text-warning',\r\n danger: 'text-danger',\r\n info: 'text-info',\r\n help: 'text-help',\r\n};\r\n\r\nconst UNDERLINE_CLASSES: Record<LinkUnderline, string> = {\r\n always: 'underline underline-offset-2',\r\n hover: 'no-underline underline-offset-2 hover:underline',\r\n none: 'no-underline',\r\n};\r\n\r\n/**\r\n * `<a mfLink href=\"/ayarlar\">Ayarlar</a>` — düz metin içine gömülü bağlantılar\r\n * için (ör. \"Zaten hesabınız var mı? Giriş yapın\"). Navigasyon bağlantıları\r\n * (sidebar, tabs, breadcrumb) KENDİ bileşenlerinin stilini taşır, bu\r\n * directive'i KULLANMAZ — `Link` SADECE metin akışı içindeki bağlantılar için.\r\n */\r\n@Directive({\r\n selector: 'a[mfLink]',\r\n host: { '[class]': 'classes()' },\r\n})\r\nexport class Link {\r\n readonly tone = input<MfTone>('primary');\r\n readonly underline = input<LinkUnderline>('hover');\r\n\r\n protected readonly classes = computed(() =>\r\n cn(\r\n 'transition-colors duration-fast ease-emphasis focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring',\r\n TONE_CLASSES[this.tone()],\r\n UNDERLINE_CLASSES[this.underline()],\r\n ),\r\n );\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAKA,MAAM,YAAY,GAA2B;AAC3C,IAAA,OAAO,EAAE,6BAA6B;AACtC,IAAA,OAAO,EAAE,sCAAsC;AAC/C,IAAA,OAAO,EAAE,cAAc;AACvB,IAAA,OAAO,EAAE,cAAc;AACvB,IAAA,MAAM,EAAE,aAAa;AACrB,IAAA,IAAI,EAAE,WAAW;AACjB,IAAA,IAAI,EAAE,WAAW;CAClB;AAED,MAAM,iBAAiB,GAAkC;AACvD,IAAA,MAAM,EAAE,8BAA8B;AACtC,IAAA,KAAK,EAAE,iDAAiD;AACxD,IAAA,IAAI,EAAE,cAAc;CACrB;AAED;;;;;AAKG;MAKU,IAAI,CAAA;IACN,IAAI,GAAG,KAAK,CAAS,SAAS;6EAAC;IAC/B,SAAS,GAAG,KAAK,CAAgB,OAAO;kFAAC;IAE/B,OAAO,GAAG,QAAQ,CAAC,MACpC,EAAE,CACA,6JAA6J,EAC7J,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EACzB,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CACpC;gFACF;uGAVU,IAAI,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAJ,IAAI,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,WAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAJ,IAAI,EAAA,UAAA,EAAA,CAAA;kBAJhB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE;AACjC,iBAAA;;;AC9BD;;AAEG;;"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as i1 from '@angular/aria/menu';
|
|
2
|
+
import { Menu as Menu$1, MenuItem as MenuItem$1, MenuTrigger as MenuTrigger$1 } from '@angular/aria/menu';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { Component, inject, computed, Directive } from '@angular/core';
|
|
5
|
+
import { cn } from '@mesgflow/ui-kit/core';
|
|
6
|
+
import { cva } from 'class-variance-authority';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `<mf-menu #menu="ngMenu" (itemSelected)="onSelect($event)"><button mfMenuItem value="a">A</button></mf-menu>`
|
|
10
|
+
* — genelde bir `mf-popover` içine konur, tetikleyici için `mfMenuTrigger`
|
|
11
|
+
* kullanılır (bkz. `menu-trigger.ts`). ARIA/klavye (ok tuşu navigasyonu,
|
|
12
|
+
* typeahead, alt-menü açma) `@angular/aria/menu`'nün `Menu` pattern'inden
|
|
13
|
+
* `hostDirectives` ile geliyor — `Select`'in listbox'ıyla AYNI görsel dil
|
|
14
|
+
* (rounded-lg, shadow-2, bg-overlay).
|
|
15
|
+
*
|
|
16
|
+
* `hostDirectives` uygulanan bir directive'in KENDİ `exportAs`'ı (`ngMenu`)
|
|
17
|
+
* host elemanda hâlâ kullanılabilir (Angular directive composition API'sinin
|
|
18
|
+
* dokümante edilmiş davranışı) — bu yüzden `MenuTrigger`'ın `[menu]`
|
|
19
|
+
* girdisine doğrudan `#menu="ngMenu"` verilebiliyor, ayrı bir forward'a
|
|
20
|
+
* gerek yok.
|
|
21
|
+
*/
|
|
22
|
+
class Menu {
|
|
23
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Menu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
24
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: Menu, isStandalone: true, selector: "mf-menu", host: { classAttribute: "block max-h-64 min-w-[10rem] overflow-auto rounded-lg border border-hairline bg-overlay p-1 text-sm shadow-2" }, exportAs: ["mfMenu"], hostDirectives: [{ directive: i1.Menu, inputs: ["wrap", "wrap", "disabled", "disabled", "typeaheadDelay", "typeaheadDelay"], outputs: ["itemSelected", "itemSelected"] }], ngImport: i0, template: '<ng-content />', isInline: true });
|
|
25
|
+
}
|
|
26
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: Menu, decorators: [{
|
|
27
|
+
type: Component,
|
|
28
|
+
args: [{
|
|
29
|
+
selector: 'mf-menu',
|
|
30
|
+
exportAs: 'mfMenu',
|
|
31
|
+
hostDirectives: [
|
|
32
|
+
{
|
|
33
|
+
directive: Menu$1,
|
|
34
|
+
inputs: ['wrap', 'disabled', 'typeaheadDelay'],
|
|
35
|
+
outputs: ['itemSelected'],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
host: {
|
|
39
|
+
class: 'block max-h-64 min-w-[10rem] overflow-auto rounded-lg border border-hairline bg-overlay p-1 text-sm shadow-2',
|
|
40
|
+
},
|
|
41
|
+
template: '<ng-content />',
|
|
42
|
+
}]
|
|
43
|
+
}] });
|
|
44
|
+
|
|
45
|
+
const menuItemVariants = cva('flex cursor-pointer items-center gap-2 rounded-sm px-2.5 py-1.5 text-fg-muted transition-colors duration-fast ease-emphasis active:scale-[0.99]', {
|
|
46
|
+
variants: {
|
|
47
|
+
active: {
|
|
48
|
+
true: 'bg-surface-alt text-fg',
|
|
49
|
+
false: '',
|
|
50
|
+
},
|
|
51
|
+
disabled: {
|
|
52
|
+
true: 'pointer-events-none opacity-50 active:scale-100',
|
|
53
|
+
false: '',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
defaultVariants: { active: false, disabled: false },
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
/** `<button mfMenuItem value="delete">Sil</button>` — `mf-menu` içine konur. */
|
|
60
|
+
class MenuItem {
|
|
61
|
+
ariaMenuItem = inject(MenuItem$1);
|
|
62
|
+
classes = computed(() => cn(menuItemVariants({
|
|
63
|
+
active: this.ariaMenuItem.active(),
|
|
64
|
+
disabled: this.ariaMenuItem.disabled(),
|
|
65
|
+
})), /* @ts-ignore */
|
|
66
|
+
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
67
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: MenuItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
68
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: MenuItem, isStandalone: true, selector: "button[mfMenuItem], div[mfMenuItem]", host: { properties: { "class": "classes()" } }, hostDirectives: [{ directive: i1.MenuItem, inputs: ["value", "value", "disabled", "disabled", "id", "id"] }], ngImport: i0 });
|
|
69
|
+
}
|
|
70
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: MenuItem, decorators: [{
|
|
71
|
+
type: Directive,
|
|
72
|
+
args: [{
|
|
73
|
+
selector: 'button[mfMenuItem], div[mfMenuItem]',
|
|
74
|
+
hostDirectives: [{ directive: MenuItem$1, inputs: ['value', 'disabled', 'id'] }],
|
|
75
|
+
host: { '[class]': 'classes()' },
|
|
76
|
+
}]
|
|
77
|
+
}] });
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* `<button mfMenuTrigger [menu]="menuRef" cdkOverlayOrigin #origin="cdkOverlayOrigin">Aç</button>`
|
|
81
|
+
* — `[menu]`'ye `mf-menu`'nün `#ref="ngMenu"` template referansını ver.
|
|
82
|
+
* Pozisyonlama (floating panel) bu directive'in İŞİ DEĞİL — `@angular/aria/menu`
|
|
83
|
+
* headless, konum bilgisi taşımıyor; `mf-popover`'ın `[open]="trigger.expanded()"`
|
|
84
|
+
* ile beslenmesi gerekiyor (bkz. playground'daki Menu demosu, `(closed)`
|
|
85
|
+
* çıktısında `trigger.close()` çağırarak iki state'i senkron tutma deseni).
|
|
86
|
+
*/
|
|
87
|
+
class MenuTrigger {
|
|
88
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: MenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
89
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: MenuTrigger, isStandalone: true, selector: "[mfMenuTrigger]", exportAs: ["mfMenuTrigger"], hostDirectives: [{ directive: i1.MenuTrigger, inputs: ["menu", "menu", "disabled", "disabled"] }], ngImport: i0 });
|
|
90
|
+
}
|
|
91
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: MenuTrigger, decorators: [{
|
|
92
|
+
type: Directive,
|
|
93
|
+
args: [{
|
|
94
|
+
selector: '[mfMenuTrigger]',
|
|
95
|
+
exportAs: 'mfMenuTrigger',
|
|
96
|
+
hostDirectives: [{ directive: MenuTrigger$1, inputs: ['menu', 'disabled'] }],
|
|
97
|
+
}]
|
|
98
|
+
}] });
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Generated bundle index. Do not edit.
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
export { Menu, MenuItem, MenuTrigger, menuItemVariants };
|
|
105
|
+
//# sourceMappingURL=mesgflow-ui-kit-menu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-menu.mjs","sources":["../../../projects/ui-kit/menu/menu.ts","../../../projects/ui-kit/menu/menu.variants.ts","../../../projects/ui-kit/menu/menu-item.ts","../../../projects/ui-kit/menu/menu-trigger.ts","../../../projects/ui-kit/menu/mesgflow-ui-kit-menu.ts"],"sourcesContent":["import { Menu as AriaMenu } from '@angular/aria/menu';\r\nimport { Component } from '@angular/core';\r\n\r\n/**\r\n * `<mf-menu #menu=\"ngMenu\" (itemSelected)=\"onSelect($event)\"><button mfMenuItem value=\"a\">A</button></mf-menu>`\r\n * — genelde bir `mf-popover` içine konur, tetikleyici için `mfMenuTrigger`\r\n * kullanılır (bkz. `menu-trigger.ts`). ARIA/klavye (ok tuşu navigasyonu,\r\n * typeahead, alt-menü açma) `@angular/aria/menu`'nün `Menu` pattern'inden\r\n * `hostDirectives` ile geliyor — `Select`'in listbox'ıyla AYNI görsel dil\r\n * (rounded-lg, shadow-2, bg-overlay).\r\n *\r\n * `hostDirectives` uygulanan bir directive'in KENDİ `exportAs`'ı (`ngMenu`)\r\n * host elemanda hâlâ kullanılabilir (Angular directive composition API'sinin\r\n * dokümante edilmiş davranışı) — bu yüzden `MenuTrigger`'ın `[menu]`\r\n * girdisine doğrudan `#menu=\"ngMenu\"` verilebiliyor, ayrı bir forward'a\r\n * gerek yok.\r\n */\r\n@Component({\r\n selector: 'mf-menu',\r\n exportAs: 'mfMenu',\r\n hostDirectives: [\r\n {\r\n directive: AriaMenu,\r\n inputs: ['wrap', 'disabled', 'typeaheadDelay'],\r\n outputs: ['itemSelected'],\r\n },\r\n ],\r\n host: {\r\n class:\r\n 'block max-h-64 min-w-[10rem] overflow-auto rounded-lg border border-hairline bg-overlay p-1 text-sm shadow-2',\r\n },\r\n template: '<ng-content />',\r\n})\r\nexport class Menu {}\r\n","import { cva, type VariantProps } from 'class-variance-authority';\r\n\r\nexport const menuItemVariants = cva(\r\n 'flex cursor-pointer items-center gap-2 rounded-sm px-2.5 py-1.5 text-fg-muted transition-colors duration-fast ease-emphasis active:scale-[0.99]',\r\n {\r\n variants: {\r\n active: {\r\n true: 'bg-surface-alt text-fg',\r\n false: '',\r\n },\r\n disabled: {\r\n true: 'pointer-events-none opacity-50 active:scale-100',\r\n false: '',\r\n },\r\n },\r\n defaultVariants: { active: false, disabled: false },\r\n },\r\n);\r\n\r\nexport type MenuItemActive = VariantProps<typeof menuItemVariants>['active'];\r\n","import { MenuItem as AriaMenuItem } from '@angular/aria/menu';\r\nimport { Directive, computed, inject } from '@angular/core';\r\nimport { cn } from '@mesgflow/ui-kit/core';\r\nimport { menuItemVariants } from './menu.variants';\r\n\r\n/** `<button mfMenuItem value=\"delete\">Sil</button>` — `mf-menu` içine konur. */\r\n@Directive({\r\n selector: 'button[mfMenuItem], div[mfMenuItem]',\r\n hostDirectives: [{ directive: AriaMenuItem, inputs: ['value', 'disabled', 'id'] }],\r\n host: { '[class]': 'classes()' },\r\n})\r\nexport class MenuItem<V> {\r\n private readonly ariaMenuItem = inject<AriaMenuItem<V>>(AriaMenuItem);\r\n\r\n protected readonly classes = computed(() =>\r\n cn(\r\n menuItemVariants({\r\n active: this.ariaMenuItem.active(),\r\n disabled: this.ariaMenuItem.disabled(),\r\n }),\r\n ),\r\n );\r\n}\r\n","import { MenuTrigger as AriaMenuTrigger } from '@angular/aria/menu';\r\nimport { Directive } from '@angular/core';\r\n\r\n/**\r\n * `<button mfMenuTrigger [menu]=\"menuRef\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">Aç</button>`\r\n * — `[menu]`'ye `mf-menu`'nün `#ref=\"ngMenu\"` template referansını ver.\r\n * Pozisyonlama (floating panel) bu directive'in İŞİ DEĞİL — `@angular/aria/menu`\r\n * headless, konum bilgisi taşımıyor; `mf-popover`'ın `[open]=\"trigger.expanded()\"`\r\n * ile beslenmesi gerekiyor (bkz. playground'daki Menu demosu, `(closed)`\r\n * çıktısında `trigger.close()` çağırarak iki state'i senkron tutma deseni).\r\n */\r\n@Directive({\r\n selector: '[mfMenuTrigger]',\r\n exportAs: 'mfMenuTrigger',\r\n hostDirectives: [{ directive: AriaMenuTrigger, inputs: ['menu', 'disabled'] }],\r\n})\r\nexport class MenuTrigger {}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["AriaMenu","AriaMenuItem","AriaMenuTrigger"],"mappings":"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"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { model, input, computed, signal, forwardRef, Component } from '@angular/core';
|
|
3
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import { Icon } from '@mesgflow/ui-kit/icon';
|
|
5
|
+
import { Input, InputGroup, InputPrefix, InputSuffix } from '@mesgflow/ui-kit/input';
|
|
6
|
+
|
|
7
|
+
/** Sürükleyerek değiştirmede kaç piksel sürüklemenin BİR `step()` ilerlemeye karşılık geldiği — Figma/After Effects gibi araçlardaki yaygın "scrubber" deseniyle AYNI kaba değer. */
|
|
8
|
+
const DRAG_PIXELS_PER_STEP = 4;
|
|
9
|
+
/**
|
|
10
|
+
* `<mf-number-input [(value)]="padding" [min]="0" [max]="64" [step]="4" unit="px" />`
|
|
11
|
+
*
|
|
12
|
+
* `Select`'in `ControlValueAccessor` deseni tekrarlanıyor (bkz. select.ts
|
|
13
|
+
* üstündeki not) — native değil, `NG_VALUE_ACCESSOR`'ı KENDİSİ sağlamak
|
|
14
|
+
* zorunda. Klavye (yukarı/aşağı ok, PageUp/PageDown ±10×step) + stepper
|
|
15
|
+
* butonları (mouse-only, `tabindex="-1"` — gerçek `spinbutton` semantiği
|
|
16
|
+
* input'un kendisinde) HER ZAMAN TAM işlevsellik sağlıyor.
|
|
17
|
+
*
|
|
18
|
+
* Sürükleyerek değiştirme (Kademe 12 paket BV — önceden "v1 kapsamı dışı"
|
|
19
|
+
* bırakılmıştı) — SADECE `unit()` VERİLMİŞSE (`px` etiketi gibi) o etiket
|
|
20
|
+
* yatay sürüklenebilir bir "scrubber" olur (`pointerdown`+`setPointerCapture`
|
|
21
|
+
* ile sürükleme YAKALANIR, imleç `ew-resize` olur). `unit` YOKSA (boş
|
|
22
|
+
* string) sürükleme EKLENMEDİ — dekoratif bir tutamaç elementi olmadan
|
|
23
|
+
* kullanıcının "burayı sürükleyebilirim" sezgisi YOK, YENİ bir görsel
|
|
24
|
+
* eleman eklemek gerekirdi (kapsam dışı). Bu, ERİŞİLEBİLİRLİK açısından
|
|
25
|
+
* bir GERİLEME DEĞİL — klavye ZATEN aynı işlevselliği (yukarı/aşağı ok)
|
|
26
|
+
* tam olarak sağlıyor, sürükleme SADECE mouse kullanıcıları için EK bir
|
|
27
|
+
* kısayol (stepper butonlarının `tabindex="-1"` olmasıyla AYNI ilke).
|
|
28
|
+
*/
|
|
29
|
+
class NumberInput {
|
|
30
|
+
value = model(null, /* @ts-ignore */
|
|
31
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
32
|
+
min = input(null, /* @ts-ignore */
|
|
33
|
+
...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
34
|
+
max = input(null, /* @ts-ignore */
|
|
35
|
+
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
36
|
+
step = input(1, /* @ts-ignore */
|
|
37
|
+
...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
|
|
38
|
+
unit = input('', /* @ts-ignore */
|
|
39
|
+
...(ngDevMode ? [{ debugName: "unit" }] : /* istanbul ignore next */ []));
|
|
40
|
+
disabled = input(false, /* @ts-ignore */
|
|
41
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
42
|
+
hasError = input(false, /* @ts-ignore */
|
|
43
|
+
...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
44
|
+
ariaLabel = input('', /* @ts-ignore */
|
|
45
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
46
|
+
onChange = () => { };
|
|
47
|
+
onTouched = () => { };
|
|
48
|
+
canDecrement = computed(() => !this.disabled() && (this.min() == null || (this.value() ?? 0) > this.min()), /* @ts-ignore */
|
|
49
|
+
...(ngDevMode ? [{ debugName: "canDecrement" }] : /* istanbul ignore next */ []));
|
|
50
|
+
canIncrement = computed(() => !this.disabled() && (this.max() == null || (this.value() ?? 0) < this.max()), /* @ts-ignore */
|
|
51
|
+
...(ngDevMode ? [{ debugName: "canIncrement" }] : /* istanbul ignore next */ []));
|
|
52
|
+
dragging = signal(false, /* @ts-ignore */
|
|
53
|
+
...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
|
|
54
|
+
dragStartClientX = 0;
|
|
55
|
+
dragStartValue = 0;
|
|
56
|
+
writeValue(value) {
|
|
57
|
+
this.value.set(value);
|
|
58
|
+
}
|
|
59
|
+
registerOnChange(fn) {
|
|
60
|
+
this.onChange = fn;
|
|
61
|
+
}
|
|
62
|
+
registerOnTouched(fn) {
|
|
63
|
+
this.onTouched = fn;
|
|
64
|
+
}
|
|
65
|
+
clamp(next) {
|
|
66
|
+
let v = next;
|
|
67
|
+
if (this.min() != null)
|
|
68
|
+
v = Math.max(this.min(), v);
|
|
69
|
+
if (this.max() != null)
|
|
70
|
+
v = Math.min(this.max(), v);
|
|
71
|
+
return v;
|
|
72
|
+
}
|
|
73
|
+
adjust(delta) {
|
|
74
|
+
if (this.disabled())
|
|
75
|
+
return;
|
|
76
|
+
const next = this.clamp((this.value() ?? 0) + delta);
|
|
77
|
+
this.value.set(next);
|
|
78
|
+
this.onChange(next);
|
|
79
|
+
}
|
|
80
|
+
onInputChange(raw) {
|
|
81
|
+
const parsed = raw.trim() === '' ? null : Number(raw);
|
|
82
|
+
const next = parsed === null || Number.isNaN(parsed) ? null : this.clamp(parsed);
|
|
83
|
+
this.value.set(next);
|
|
84
|
+
this.onChange(next);
|
|
85
|
+
}
|
|
86
|
+
onBlur() {
|
|
87
|
+
this.onTouched();
|
|
88
|
+
}
|
|
89
|
+
onKeydown(event) {
|
|
90
|
+
switch (event.key) {
|
|
91
|
+
case 'ArrowUp':
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
this.adjust(this.step());
|
|
94
|
+
break;
|
|
95
|
+
case 'ArrowDown':
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
this.adjust(-this.step());
|
|
98
|
+
break;
|
|
99
|
+
case 'PageUp':
|
|
100
|
+
event.preventDefault();
|
|
101
|
+
this.adjust(this.step() * 10);
|
|
102
|
+
break;
|
|
103
|
+
case 'PageDown':
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
this.adjust(-this.step() * 10);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// --- Sürükleyerek değiştirme (Kademe 12 paket BV) — bkz. class üstündeki not. ---
|
|
110
|
+
onUnitPointerDown(event) {
|
|
111
|
+
if (this.disabled())
|
|
112
|
+
return;
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
this.dragging.set(true);
|
|
115
|
+
this.dragStartClientX = event.clientX;
|
|
116
|
+
this.dragStartValue = this.value() ?? 0;
|
|
117
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
118
|
+
}
|
|
119
|
+
onUnitPointerMove(event) {
|
|
120
|
+
if (!this.dragging())
|
|
121
|
+
return;
|
|
122
|
+
const deltaSteps = Math.round((event.clientX - this.dragStartClientX) / DRAG_PIXELS_PER_STEP);
|
|
123
|
+
const next = this.clamp(this.dragStartValue + deltaSteps * this.step());
|
|
124
|
+
if (next !== this.value()) {
|
|
125
|
+
this.value.set(next);
|
|
126
|
+
this.onChange(next);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
onUnitPointerUp(event) {
|
|
130
|
+
if (!this.dragging())
|
|
131
|
+
return;
|
|
132
|
+
this.dragging.set(false);
|
|
133
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
134
|
+
this.onTouched();
|
|
135
|
+
}
|
|
136
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NumberInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
137
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: NumberInput, isStandalone: true, selector: "mf-number-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { classAttribute: "inline-flex" }, providers: [
|
|
138
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NumberInput), multi: true },
|
|
139
|
+
], exportAs: ["mfNumberInput"], ngImport: i0, template: "<mf-input-group [padded]=\"false\" [hasError]=\"hasError()\" [disabled]=\"disabled()\">\r\n <button\r\n type=\"button\"\r\n mfInputPrefix\r\n class=\"w-8 justify-center rounded-s-md text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-alt hover:text-fg disabled:pointer-events-none disabled:opacity-50\"\r\n [disabled]=\"!canDecrement()\"\r\n (click)=\"adjust(-step())\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n >\r\n <span mfIcon [size]=\"16\">remove</span>\r\n </button>\r\n <input\r\n mfInput\r\n type=\"text\"\r\n inputmode=\"decimal\"\r\n role=\"spinbutton\"\r\n class=\"min-w-0 flex-1 border-0 bg-transparent px-1 py-1.5 text-center shadow-none focus-visible:outline-none disabled:cursor-not-allowed\"\r\n [value]=\"value() ?? ''\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"value()\"\r\n (input)=\"onInputChange($any($event.target).value)\"\r\n (blur)=\"onBlur()\"\r\n (keydown)=\"onKeydown($event)\"\r\n />\r\n @if (unit()) {\r\n <span\r\n class=\"number-input-unit flex shrink-0 items-center pe-2 text-sm text-fg-subtle select-none\"\r\n [class.cursor-ew-resize]=\"!disabled()\"\r\n aria-hidden=\"true\"\r\n (pointerdown)=\"onUnitPointerDown($event)\"\r\n (pointermove)=\"onUnitPointerMove($event)\"\r\n (pointerup)=\"onUnitPointerUp($event)\"\r\n >{{ unit() }}</span\r\n >\r\n }\r\n <button\r\n type=\"button\"\r\n mfInputSuffix\r\n class=\"w-8 justify-center rounded-e-md text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-alt hover:text-fg disabled:pointer-events-none disabled:opacity-50\"\r\n [disabled]=\"!canIncrement()\"\r\n (click)=\"adjust(step())\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n >\r\n <span mfIcon [size]=\"16\">add</span>\r\n </button>\r\n</mf-input-group>\r\n", dependencies: [{ kind: "directive", type: Icon, selector: "span[mfIcon]", inputs: ["size", "filled"] }, { kind: "directive", type: Input, selector: "input[mfInput]:not([type=checkbox]):not([type=radio]), textarea[mfInput]", inputs: ["size", "hasError", "autosize", "minRows", "maxRows"] }, { kind: "component", type: InputGroup, selector: "mf-input-group", inputs: ["size", "disabled", "hasError", "padded", "wrap"], exportAs: ["mfInputGroup"] }, { kind: "directive", type: InputPrefix, selector: "[mfInputPrefix]", inputs: ["addon"] }, { kind: "directive", type: InputSuffix, selector: "[mfInputSuffix]", inputs: ["addon"] }] });
|
|
140
|
+
}
|
|
141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NumberInput, decorators: [{
|
|
142
|
+
type: Component,
|
|
143
|
+
args: [{ selector: 'mf-number-input', exportAs: 'mfNumberInput', host: { class: 'inline-flex' }, imports: [Icon, Input, InputGroup, InputPrefix, InputSuffix], providers: [
|
|
144
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NumberInput), multi: true },
|
|
145
|
+
], template: "<mf-input-group [padded]=\"false\" [hasError]=\"hasError()\" [disabled]=\"disabled()\">\r\n <button\r\n type=\"button\"\r\n mfInputPrefix\r\n class=\"w-8 justify-center rounded-s-md text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-alt hover:text-fg disabled:pointer-events-none disabled:opacity-50\"\r\n [disabled]=\"!canDecrement()\"\r\n (click)=\"adjust(-step())\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n >\r\n <span mfIcon [size]=\"16\">remove</span>\r\n </button>\r\n <input\r\n mfInput\r\n type=\"text\"\r\n inputmode=\"decimal\"\r\n role=\"spinbutton\"\r\n class=\"min-w-0 flex-1 border-0 bg-transparent px-1 py-1.5 text-center shadow-none focus-visible:outline-none disabled:cursor-not-allowed\"\r\n [value]=\"value() ?? ''\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"value()\"\r\n (input)=\"onInputChange($any($event.target).value)\"\r\n (blur)=\"onBlur()\"\r\n (keydown)=\"onKeydown($event)\"\r\n />\r\n @if (unit()) {\r\n <span\r\n class=\"number-input-unit flex shrink-0 items-center pe-2 text-sm text-fg-subtle select-none\"\r\n [class.cursor-ew-resize]=\"!disabled()\"\r\n aria-hidden=\"true\"\r\n (pointerdown)=\"onUnitPointerDown($event)\"\r\n (pointermove)=\"onUnitPointerMove($event)\"\r\n (pointerup)=\"onUnitPointerUp($event)\"\r\n >{{ unit() }}</span\r\n >\r\n }\r\n <button\r\n type=\"button\"\r\n mfInputSuffix\r\n class=\"w-8 justify-center rounded-e-md text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-alt hover:text-fg disabled:pointer-events-none disabled:opacity-50\"\r\n [disabled]=\"!canIncrement()\"\r\n (click)=\"adjust(step())\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n >\r\n <span mfIcon [size]=\"16\">add</span>\r\n </button>\r\n</mf-input-group>\r\n" }]
|
|
146
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], 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 }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Generated bundle index. Do not edit.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
export { NumberInput };
|
|
153
|
+
//# sourceMappingURL=mesgflow-ui-kit-number-input.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-number-input.mjs","sources":["../../../projects/ui-kit/number-input/number-input.ts","../../../projects/ui-kit/number-input/number-input.html","../../../projects/ui-kit/number-input/mesgflow-ui-kit-number-input.ts"],"sourcesContent":["import { Component, computed, forwardRef, input, model, signal } from '@angular/core';\r\nimport { NG_VALUE_ACCESSOR, type ControlValueAccessor } from '@angular/forms';\r\nimport { Icon } from '@mesgflow/ui-kit/icon';\r\nimport { Input, InputGroup, InputPrefix, InputSuffix } from '@mesgflow/ui-kit/input';\r\n\r\n/** Sürükleyerek değiştirmede kaç piksel sürüklemenin BİR `step()` ilerlemeye karşılık geldiği — Figma/After Effects gibi araçlardaki yaygın \"scrubber\" deseniyle AYNI kaba değer. */\r\nconst DRAG_PIXELS_PER_STEP = 4;\r\n\r\n/**\r\n * `<mf-number-input [(value)]=\"padding\" [min]=\"0\" [max]=\"64\" [step]=\"4\" unit=\"px\" />`\r\n *\r\n * `Select`'in `ControlValueAccessor` deseni tekrarlanıyor (bkz. select.ts\r\n * üstündeki not) — native değil, `NG_VALUE_ACCESSOR`'ı KENDİSİ sağlamak\r\n * zorunda. Klavye (yukarı/aşağı ok, PageUp/PageDown ±10×step) + stepper\r\n * butonları (mouse-only, `tabindex=\"-1\"` — gerçek `spinbutton` semantiği\r\n * input'un kendisinde) HER ZAMAN TAM işlevsellik sağlıyor.\r\n *\r\n * Sürükleyerek değiştirme (Kademe 12 paket BV — önceden \"v1 kapsamı dışı\"\r\n * bırakılmıştı) — SADECE `unit()` VERİLMİŞSE (`px` etiketi gibi) o etiket\r\n * yatay sürüklenebilir bir \"scrubber\" olur (`pointerdown`+`setPointerCapture`\r\n * ile sürükleme YAKALANIR, imleç `ew-resize` olur). `unit` YOKSA (boş\r\n * string) sürükleme EKLENMEDİ — dekoratif bir tutamaç elementi olmadan\r\n * kullanıcının \"burayı sürükleyebilirim\" sezgisi YOK, YENİ bir görsel\r\n * eleman eklemek gerekirdi (kapsam dışı). Bu, ERİŞİLEBİLİRLİK açısından\r\n * bir GERİLEME DEĞİL — klavye ZATEN aynı işlevselliği (yukarı/aşağı ok)\r\n * tam olarak sağlıyor, sürükleme SADECE mouse kullanıcıları için EK bir\r\n * kısayol (stepper butonlarının `tabindex=\"-1\"` olmasıyla AYNI ilke).\r\n */\r\n@Component({\r\n selector: 'mf-number-input',\r\n exportAs: 'mfNumberInput',\r\n host: { class: 'inline-flex' },\r\n imports: [Icon, Input, InputGroup, InputPrefix, InputSuffix],\r\n templateUrl: './number-input.html',\r\n providers: [\r\n { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NumberInput), multi: true },\r\n ],\r\n})\r\nexport class NumberInput implements ControlValueAccessor {\r\n readonly value = model<number | null>(null);\r\n readonly min = input<number | null>(null);\r\n readonly max = input<number | null>(null);\r\n readonly step = input(1);\r\n readonly unit = input('');\r\n readonly disabled = input(false);\r\n readonly hasError = input(false);\r\n readonly ariaLabel = input('');\r\n\r\n private onChange: (value: number | null) => void = () => {};\r\n private onTouched: () => void = () => {};\r\n\r\n protected readonly canDecrement = computed(\r\n () => !this.disabled() && (this.min() == null || (this.value() ?? 0) > this.min()!),\r\n );\r\n protected readonly canIncrement = computed(\r\n () => !this.disabled() && (this.max() == null || (this.value() ?? 0) < this.max()!),\r\n );\r\n\r\n protected readonly dragging = signal(false);\r\n private dragStartClientX = 0;\r\n private dragStartValue = 0;\r\n\r\n writeValue(value: number | null): void {\r\n this.value.set(value);\r\n }\r\n\r\n registerOnChange(fn: (value: number | null) => void): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: () => void): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n protected clamp(next: number): number {\r\n let v = next;\r\n if (this.min() != null) v = Math.max(this.min()!, v);\r\n if (this.max() != null) v = Math.min(this.max()!, v);\r\n return v;\r\n }\r\n\r\n protected adjust(delta: number): void {\r\n if (this.disabled()) return;\r\n const next = this.clamp((this.value() ?? 0) + delta);\r\n this.value.set(next);\r\n this.onChange(next);\r\n }\r\n\r\n protected onInputChange(raw: string): void {\r\n const parsed = raw.trim() === '' ? null : Number(raw);\r\n const next = parsed === null || Number.isNaN(parsed) ? null : this.clamp(parsed);\r\n this.value.set(next);\r\n this.onChange(next);\r\n }\r\n\r\n protected onBlur(): void {\r\n this.onTouched();\r\n }\r\n\r\n protected onKeydown(event: KeyboardEvent): void {\r\n switch (event.key) {\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this.adjust(this.step());\r\n break;\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this.adjust(-this.step());\r\n break;\r\n case 'PageUp':\r\n event.preventDefault();\r\n this.adjust(this.step() * 10);\r\n break;\r\n case 'PageDown':\r\n event.preventDefault();\r\n this.adjust(-this.step() * 10);\r\n break;\r\n }\r\n }\r\n\r\n // --- Sürükleyerek değiştirme (Kademe 12 paket BV) — bkz. class üstündeki not. ---\r\n protected onUnitPointerDown(event: PointerEvent): void {\r\n if (this.disabled()) return;\r\n event.preventDefault();\r\n this.dragging.set(true);\r\n this.dragStartClientX = event.clientX;\r\n this.dragStartValue = this.value() ?? 0;\r\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\r\n }\r\n\r\n protected onUnitPointerMove(event: PointerEvent): void {\r\n if (!this.dragging()) return;\r\n const deltaSteps = Math.round((event.clientX - this.dragStartClientX) / DRAG_PIXELS_PER_STEP);\r\n const next = this.clamp(this.dragStartValue + deltaSteps * this.step());\r\n if (next !== this.value()) {\r\n this.value.set(next);\r\n this.onChange(next);\r\n }\r\n }\r\n\r\n protected onUnitPointerUp(event: PointerEvent): void {\r\n if (!this.dragging()) return;\r\n this.dragging.set(false);\r\n (event.currentTarget as HTMLElement).releasePointerCapture(event.pointerId);\r\n this.onTouched();\r\n }\r\n}\r\n","<mf-input-group [padded]=\"false\" [hasError]=\"hasError()\" [disabled]=\"disabled()\">\r\n <button\r\n type=\"button\"\r\n mfInputPrefix\r\n class=\"w-8 justify-center rounded-s-md text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-alt hover:text-fg disabled:pointer-events-none disabled:opacity-50\"\r\n [disabled]=\"!canDecrement()\"\r\n (click)=\"adjust(-step())\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n >\r\n <span mfIcon [size]=\"16\">remove</span>\r\n </button>\r\n <input\r\n mfInput\r\n type=\"text\"\r\n inputmode=\"decimal\"\r\n role=\"spinbutton\"\r\n class=\"min-w-0 flex-1 border-0 bg-transparent px-1 py-1.5 text-center shadow-none focus-visible:outline-none disabled:cursor-not-allowed\"\r\n [value]=\"value() ?? ''\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"value()\"\r\n (input)=\"onInputChange($any($event.target).value)\"\r\n (blur)=\"onBlur()\"\r\n (keydown)=\"onKeydown($event)\"\r\n />\r\n @if (unit()) {\r\n <span\r\n class=\"number-input-unit flex shrink-0 items-center pe-2 text-sm text-fg-subtle select-none\"\r\n [class.cursor-ew-resize]=\"!disabled()\"\r\n aria-hidden=\"true\"\r\n (pointerdown)=\"onUnitPointerDown($event)\"\r\n (pointermove)=\"onUnitPointerMove($event)\"\r\n (pointerup)=\"onUnitPointerUp($event)\"\r\n >{{ unit() }}</span\r\n >\r\n }\r\n <button\r\n type=\"button\"\r\n mfInputSuffix\r\n class=\"w-8 justify-center rounded-e-md text-fg-subtle transition-colors duration-fast ease-emphasis hover:bg-surface-alt hover:text-fg disabled:pointer-events-none disabled:opacity-50\"\r\n [disabled]=\"!canIncrement()\"\r\n (click)=\"adjust(step())\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n >\r\n <span mfIcon [size]=\"16\">add</span>\r\n </button>\r\n</mf-input-group>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { model, input, inject, computed, viewChildren, forwardRef, Component } from '@angular/core';
|
|
3
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import { ValueAccessorBase, MF_OTP_INPUT_LABELS } from '@mesgflow/ui-kit/core';
|
|
5
|
+
import { Input } from '@mesgflow/ui-kit/input';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `<mf-otp-input [(value)]="code" [length]="6" />` — her biri TEK bir
|
|
9
|
+
* hane taşıyan `length()` kadar kutu. Değer İÇSEL olarak `length()`
|
|
10
|
+
* uzunluğa boşlukla ("henüz doldurulmadı") doldurulur, SADECE SONDAKİ
|
|
11
|
+
* boşluklar `value` model'ine yazılırken kesilir — ARADAKİ bir boşluk
|
|
12
|
+
* (ör. kullanıcı 3. kutuya tıklayıp DOĞRUDAN yazarsa, 1-2 boş kalır)
|
|
13
|
+
* teknik olarak MÜMKÜN ama normal sıralı doldurma/yapıştırma akışında
|
|
14
|
+
* hiç OLUŞMAZ.
|
|
15
|
+
*
|
|
16
|
+
* Çoklu karakter TEK bir kutuya girerse (mobil SMS OTP otomatik doldurma
|
|
17
|
+
* — işletim sistemi TÜM kodu ilk kutunun `input` event'ine basar) VEYA
|
|
18
|
+
* yapıştırılırsa, `fillFrom(0, ...)` TÜM kutuları doldurur — ikisi de
|
|
19
|
+
* AYNI yardımcıyı paylaşıyor.
|
|
20
|
+
*/
|
|
21
|
+
class OtpInput extends ValueAccessorBase {
|
|
22
|
+
value = model('', /* @ts-ignore */
|
|
23
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
24
|
+
length = input(6, /* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [{ debugName: "length" }] : /* istanbul ignore next */ []));
|
|
26
|
+
disabled = input(false, /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
28
|
+
hasError = input(false, /* @ts-ignore */
|
|
29
|
+
...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
30
|
+
ariaLabel = input(/* @ts-ignore */
|
|
31
|
+
...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
32
|
+
otpLabels = inject(MF_OTP_INPUT_LABELS);
|
|
33
|
+
effectiveAriaLabel = computed(() => this.ariaLabel() ?? this.otpLabels().ariaLabel, /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "effectiveAriaLabel" }] : /* istanbul ignore next */ []));
|
|
35
|
+
indexes = computed(() => Array.from({ length: this.length() }, (_, i) => i), /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "indexes" }] : /* istanbul ignore next */ []));
|
|
37
|
+
boxes = viewChildren('boxEl', /* @ts-ignore */
|
|
38
|
+
...(ngDevMode ? [{ debugName: "boxes" }] : /* istanbul ignore next */ []));
|
|
39
|
+
writeValue(value) {
|
|
40
|
+
this.value.set(value ?? '');
|
|
41
|
+
}
|
|
42
|
+
digitAt(i) {
|
|
43
|
+
const c = this.value()[i];
|
|
44
|
+
return c && c !== ' ' ? c : '';
|
|
45
|
+
}
|
|
46
|
+
onInput(i, event) {
|
|
47
|
+
const raw = event.target.value;
|
|
48
|
+
const digits = raw.replace(/\D/g, '');
|
|
49
|
+
if (digits.length > 1) {
|
|
50
|
+
// Mobil SMS otomatik doldurma — tüm kod tek bir input event'inde gelir.
|
|
51
|
+
this.fillFrom(0, digits);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.setDigit(i, digits);
|
|
55
|
+
if (digits && i < this.length() - 1)
|
|
56
|
+
this.focusBox(i + 1);
|
|
57
|
+
}
|
|
58
|
+
onKeydown(i, event) {
|
|
59
|
+
if (event.key === 'Backspace' && !this.digitAt(i) && i > 0) {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
this.setDigit(i - 1, '');
|
|
62
|
+
this.focusBox(i - 1);
|
|
63
|
+
}
|
|
64
|
+
else if (event.key === 'ArrowLeft' && i > 0) {
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
this.focusBox(i - 1);
|
|
67
|
+
}
|
|
68
|
+
else if (event.key === 'ArrowRight' && i < this.length() - 1) {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
this.focusBox(i + 1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
onPaste(event) {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
const digits = (event.clipboardData?.getData('text') ?? '').replace(/\D/g, '');
|
|
76
|
+
if (digits)
|
|
77
|
+
this.fillFrom(0, digits);
|
|
78
|
+
}
|
|
79
|
+
/** Odaklanınca mevcut haneyi SEÇER — yazmak EKLEMEK yerine DEĞİŞTİRİR (standart OTP kutusu davranışı). */
|
|
80
|
+
onFocus(event) {
|
|
81
|
+
event.target.select();
|
|
82
|
+
}
|
|
83
|
+
setDigit(i, digit) {
|
|
84
|
+
const chars = this.value().padEnd(this.length(), ' ').split('');
|
|
85
|
+
chars[i] = digit || ' ';
|
|
86
|
+
this.commit(chars.join('').replace(/ +$/, ''));
|
|
87
|
+
}
|
|
88
|
+
fillFrom(startIndex, digits) {
|
|
89
|
+
const chars = this.value().padEnd(this.length(), ' ').split('');
|
|
90
|
+
for (let j = 0; j < digits.length && startIndex + j < this.length(); j++) {
|
|
91
|
+
chars[startIndex + j] = digits[j];
|
|
92
|
+
}
|
|
93
|
+
this.commit(chars.join('').replace(/ +$/, ''));
|
|
94
|
+
this.focusBox(Math.min(startIndex + digits.length, this.length() - 1));
|
|
95
|
+
}
|
|
96
|
+
commit(next) {
|
|
97
|
+
this.value.set(next);
|
|
98
|
+
this.onChange(next);
|
|
99
|
+
this.onTouched();
|
|
100
|
+
}
|
|
101
|
+
focusBox(i) {
|
|
102
|
+
this.boxes()[i]?.nativeElement.focus();
|
|
103
|
+
}
|
|
104
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: OtpInput, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
105
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: OtpInput, isStandalone: true, selector: "mf-otp-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { classAttribute: "inline-flex gap-2" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => OtpInput), multi: true }], viewQueries: [{ propertyName: "boxes", predicate: ["boxEl"], descendants: true, isSignal: true }], exportAs: ["mfOtpInput"], usesInheritance: true, ngImport: i0, template: `
|
|
106
|
+
@for (i of indexes(); track i) {
|
|
107
|
+
<input
|
|
108
|
+
mfInput
|
|
109
|
+
#boxEl
|
|
110
|
+
type="text"
|
|
111
|
+
inputmode="numeric"
|
|
112
|
+
autocomplete="one-time-code"
|
|
113
|
+
maxlength="1"
|
|
114
|
+
class="h-11 w-11 text-center text-lg"
|
|
115
|
+
[value]="digitAt(i)"
|
|
116
|
+
[disabled]="disabled()"
|
|
117
|
+
[hasError]="hasError()"
|
|
118
|
+
[attr.aria-label]="effectiveAriaLabel() + ' ' + (i + 1) + '/' + length()"
|
|
119
|
+
(input)="onInput(i, $event)"
|
|
120
|
+
(keydown)="onKeydown(i, $event)"
|
|
121
|
+
(paste)="onPaste($event)"
|
|
122
|
+
(focus)="onFocus($event)"
|
|
123
|
+
/>
|
|
124
|
+
}
|
|
125
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: Input, selector: "input[mfInput]:not([type=checkbox]):not([type=radio]), textarea[mfInput]", inputs: ["size", "hasError", "autosize", "minRows", "maxRows"] }] });
|
|
126
|
+
}
|
|
127
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: OtpInput, decorators: [{
|
|
128
|
+
type: Component,
|
|
129
|
+
args: [{
|
|
130
|
+
selector: 'mf-otp-input',
|
|
131
|
+
exportAs: 'mfOtpInput',
|
|
132
|
+
imports: [Input],
|
|
133
|
+
host: { class: 'inline-flex gap-2' },
|
|
134
|
+
template: `
|
|
135
|
+
@for (i of indexes(); track i) {
|
|
136
|
+
<input
|
|
137
|
+
mfInput
|
|
138
|
+
#boxEl
|
|
139
|
+
type="text"
|
|
140
|
+
inputmode="numeric"
|
|
141
|
+
autocomplete="one-time-code"
|
|
142
|
+
maxlength="1"
|
|
143
|
+
class="h-11 w-11 text-center text-lg"
|
|
144
|
+
[value]="digitAt(i)"
|
|
145
|
+
[disabled]="disabled()"
|
|
146
|
+
[hasError]="hasError()"
|
|
147
|
+
[attr.aria-label]="effectiveAriaLabel() + ' ' + (i + 1) + '/' + length()"
|
|
148
|
+
(input)="onInput(i, $event)"
|
|
149
|
+
(keydown)="onKeydown(i, $event)"
|
|
150
|
+
(paste)="onPaste($event)"
|
|
151
|
+
(focus)="onFocus($event)"
|
|
152
|
+
/>
|
|
153
|
+
}
|
|
154
|
+
`,
|
|
155
|
+
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => OtpInput), multi: true }],
|
|
156
|
+
}]
|
|
157
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], boxes: [{ type: i0.ViewChildren, args: ['boxEl', { isSignal: true }] }] } });
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Generated bundle index. Do not edit.
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
export { OtpInput };
|
|
164
|
+
//# sourceMappingURL=mesgflow-ui-kit-otp-input.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesgflow-ui-kit-otp-input.mjs","sources":["../../../projects/ui-kit/otp-input/otp-input.ts","../../../projects/ui-kit/otp-input/mesgflow-ui-kit-otp-input.ts"],"sourcesContent":["import {\r\n Component,\r\n ElementRef,\r\n computed,\r\n forwardRef,\r\n inject,\r\n input,\r\n model,\r\n viewChildren,\r\n} from '@angular/core';\r\nimport { NG_VALUE_ACCESSOR, type ControlValueAccessor } from '@angular/forms';\r\nimport { MF_OTP_INPUT_LABELS, ValueAccessorBase } from '@mesgflow/ui-kit/core';\r\nimport { Input } from '@mesgflow/ui-kit/input';\r\n\r\n/**\r\n * `<mf-otp-input [(value)]=\"code\" [length]=\"6\" />` — her biri TEK bir\r\n * hane taşıyan `length()` kadar kutu. Değer İÇSEL olarak `length()`\r\n * uzunluğa boşlukla (\"henüz doldurulmadı\") doldurulur, SADECE SONDAKİ\r\n * boşluklar `value` model'ine yazılırken kesilir — ARADAKİ bir boşluk\r\n * (ör. kullanıcı 3. kutuya tıklayıp DOĞRUDAN yazarsa, 1-2 boş kalır)\r\n * teknik olarak MÜMKÜN ama normal sıralı doldurma/yapıştırma akışında\r\n * hiç OLUŞMAZ.\r\n *\r\n * Çoklu karakter TEK bir kutuya girerse (mobil SMS OTP otomatik doldurma\r\n * — işletim sistemi TÜM kodu ilk kutunun `input` event'ine basar) VEYA\r\n * yapıştırılırsa, `fillFrom(0, ...)` TÜM kutuları doldurur — ikisi de\r\n * AYNI yardımcıyı paylaşıyor.\r\n */\r\n@Component({\r\n selector: 'mf-otp-input',\r\n exportAs: 'mfOtpInput',\r\n imports: [Input],\r\n host: { class: 'inline-flex gap-2' },\r\n template: `\r\n @for (i of indexes(); track i) {\r\n <input\r\n mfInput\r\n #boxEl\r\n type=\"text\"\r\n inputmode=\"numeric\"\r\n autocomplete=\"one-time-code\"\r\n maxlength=\"1\"\r\n class=\"h-11 w-11 text-center text-lg\"\r\n [value]=\"digitAt(i)\"\r\n [disabled]=\"disabled()\"\r\n [hasError]=\"hasError()\"\r\n [attr.aria-label]=\"effectiveAriaLabel() + ' ' + (i + 1) + '/' + length()\"\r\n (input)=\"onInput(i, $event)\"\r\n (keydown)=\"onKeydown(i, $event)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus($event)\"\r\n />\r\n }\r\n `,\r\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => OtpInput), multi: true }],\r\n})\r\nexport class OtpInput extends ValueAccessorBase<string> implements ControlValueAccessor {\r\n readonly value = model('');\r\n readonly length = input(6);\r\n readonly disabled = input(false);\r\n readonly hasError = input(false);\r\n readonly ariaLabel = input<string>();\r\n\r\n private readonly otpLabels = inject(MF_OTP_INPUT_LABELS);\r\n protected readonly effectiveAriaLabel = computed(\r\n () => this.ariaLabel() ?? this.otpLabels().ariaLabel,\r\n );\r\n\r\n protected readonly indexes = computed(() => Array.from({ length: this.length() }, (_, i) => i));\r\n\r\n private readonly boxes = viewChildren<ElementRef<HTMLInputElement>>('boxEl');\r\n\r\n writeValue(value: string): void {\r\n this.value.set(value ?? '');\r\n }\r\n\r\n protected digitAt(i: number): string {\r\n const c = this.value()[i];\r\n return c && c !== ' ' ? c : '';\r\n }\r\n\r\n protected onInput(i: number, event: Event): void {\r\n const raw = (event.target as HTMLInputElement).value;\r\n const digits = raw.replace(/\\D/g, '');\r\n if (digits.length > 1) {\r\n // Mobil SMS otomatik doldurma — tüm kod tek bir input event'inde gelir.\r\n this.fillFrom(0, digits);\r\n return;\r\n }\r\n this.setDigit(i, digits);\r\n if (digits && i < this.length() - 1) this.focusBox(i + 1);\r\n }\r\n\r\n protected onKeydown(i: number, event: KeyboardEvent): void {\r\n if (event.key === 'Backspace' && !this.digitAt(i) && i > 0) {\r\n event.preventDefault();\r\n this.setDigit(i - 1, '');\r\n this.focusBox(i - 1);\r\n } else if (event.key === 'ArrowLeft' && i > 0) {\r\n event.preventDefault();\r\n this.focusBox(i - 1);\r\n } else if (event.key === 'ArrowRight' && i < this.length() - 1) {\r\n event.preventDefault();\r\n this.focusBox(i + 1);\r\n }\r\n }\r\n\r\n protected onPaste(event: ClipboardEvent): void {\r\n event.preventDefault();\r\n const digits = (event.clipboardData?.getData('text') ?? '').replace(/\\D/g, '');\r\n if (digits) this.fillFrom(0, digits);\r\n }\r\n\r\n /** Odaklanınca mevcut haneyi SEÇER — yazmak EKLEMEK yerine DEĞİŞTİRİR (standart OTP kutusu davranışı). */\r\n protected onFocus(event: FocusEvent): void {\r\n (event.target as HTMLInputElement).select();\r\n }\r\n\r\n private setDigit(i: number, digit: string): void {\r\n const chars = this.value().padEnd(this.length(), ' ').split('');\r\n chars[i] = digit || ' ';\r\n this.commit(chars.join('').replace(/ +$/, ''));\r\n }\r\n\r\n private fillFrom(startIndex: number, digits: string): void {\r\n const chars = this.value().padEnd(this.length(), ' ').split('');\r\n for (let j = 0; j < digits.length && startIndex + j < this.length(); j++) {\r\n chars[startIndex + j] = digits[j]!;\r\n }\r\n this.commit(chars.join('').replace(/ +$/, ''));\r\n this.focusBox(Math.min(startIndex + digits.length, this.length() - 1));\r\n }\r\n\r\n private commit(next: string): void {\r\n this.value.set(next);\r\n this.onChange(next);\r\n this.onTouched();\r\n }\r\n\r\n private focusBox(i: number): void {\r\n this.boxes()[i]?.nativeElement.focus();\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|