@raintonic/formaui 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +145 -0
- package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs +806 -0
- package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-cdk-form-field.mjs +86 -0
- package/fesm2022/raintonic-formaui-cdk-form-field.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-cdk-overlay.mjs +1757 -0
- package/fesm2022/raintonic-formaui-cdk-overlay.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs +287 -0
- package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-accordion.mjs +217 -0
- package/fesm2022/raintonic-formaui-components-accordion.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-alert.mjs +161 -0
- package/fesm2022/raintonic-formaui-components-alert.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs +726 -0
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-avatar.mjs +92 -0
- package/fesm2022/raintonic-formaui-components-avatar.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-badge.mjs +107 -0
- package/fesm2022/raintonic-formaui-components-badge.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-big-menu.mjs +68 -0
- package/fesm2022/raintonic-formaui-components-big-menu.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-breadcrumb.mjs +55 -0
- package/fesm2022/raintonic-formaui-components-breadcrumb.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-button-group.mjs +103 -0
- package/fesm2022/raintonic-formaui-components-button-group.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-button.mjs +241 -0
- package/fesm2022/raintonic-formaui-components-button.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-card.mjs +270 -0
- package/fesm2022/raintonic-formaui-components-card.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-checkbox.mjs +295 -0
- package/fesm2022/raintonic-formaui-components-checkbox.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-data-table.mjs +631 -0
- package/fesm2022/raintonic-formaui-components-data-table.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-date-picker.mjs +1331 -0
- package/fesm2022/raintonic-formaui-components-date-picker.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-divider.mjs +41 -0
- package/fesm2022/raintonic-formaui-components-divider.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-drawer.mjs +190 -0
- package/fesm2022/raintonic-formaui-components-drawer.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-dynamic-form.mjs +266 -0
- package/fesm2022/raintonic-formaui-components-dynamic-form.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-empty-state.mjs +33 -0
- package/fesm2022/raintonic-formaui-components-empty-state.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-file-upload.mjs +246 -0
- package/fesm2022/raintonic-formaui-components-file-upload.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-form-field.mjs +482 -0
- package/fesm2022/raintonic-formaui-components-form-field.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-icon.mjs +117 -0
- package/fesm2022/raintonic-formaui-components-icon.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-input.mjs +327 -0
- package/fesm2022/raintonic-formaui-components-input.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-list.mjs +149 -0
- package/fesm2022/raintonic-formaui-components-list.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-menu.mjs +896 -0
- package/fesm2022/raintonic-formaui-components-menu.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-number-input.mjs +345 -0
- package/fesm2022/raintonic-formaui-components-number-input.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-paginator.mjs +139 -0
- package/fesm2022/raintonic-formaui-components-paginator.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-password-input.mjs +306 -0
- package/fesm2022/raintonic-formaui-components-password-input.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-popover.mjs +451 -0
- package/fesm2022/raintonic-formaui-components-popover.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-progressbar.mjs +148 -0
- package/fesm2022/raintonic-formaui-components-progressbar.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-radio.mjs +260 -0
- package/fesm2022/raintonic-formaui-components-radio.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-select.mjs +1011 -0
- package/fesm2022/raintonic-formaui-components-select.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-side-panel.mjs +150 -0
- package/fesm2022/raintonic-formaui-components-side-panel.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-sidebar.mjs +257 -0
- package/fesm2022/raintonic-formaui-components-sidebar.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-skeleton.mjs +50 -0
- package/fesm2022/raintonic-formaui-components-skeleton.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-slider.mjs +347 -0
- package/fesm2022/raintonic-formaui-components-slider.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-spinner.mjs +63 -0
- package/fesm2022/raintonic-formaui-components-spinner.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-stepper.mjs +317 -0
- package/fesm2022/raintonic-formaui-components-stepper.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tab.mjs +197 -0
- package/fesm2022/raintonic-formaui-components-tab.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tag.mjs +78 -0
- package/fesm2022/raintonic-formaui-components-tag.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-time-picker.mjs +644 -0
- package/fesm2022/raintonic-formaui-components-time-picker.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-toggle.mjs +171 -0
- package/fesm2022/raintonic-formaui-components-toggle.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-toolbar.mjs +140 -0
- package/fesm2022/raintonic-formaui-components-toolbar.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tooltip.mjs +555 -0
- package/fesm2022/raintonic-formaui-components-tooltip.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tree-select.mjs +314 -0
- package/fesm2022/raintonic-formaui-components-tree-select.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tree-table.mjs +103 -0
- package/fesm2022/raintonic-formaui-components-tree-table.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tree.mjs +430 -0
- package/fesm2022/raintonic-formaui-components-tree.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-core.mjs +62 -0
- package/fesm2022/raintonic-formaui-core.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-services-dialog.mjs +798 -0
- package/fesm2022/raintonic-formaui-services-dialog.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-services-notification.mjs +391 -0
- package/fesm2022/raintonic-formaui-services-notification.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-services-theme.mjs +248 -0
- package/fesm2022/raintonic-formaui-services-theme.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-test-utils.mjs +66 -0
- package/fesm2022/raintonic-formaui-test-utils.mjs.map +1 -0
- package/fesm2022/raintonic-formaui.mjs +15 -0
- package/fesm2022/raintonic-formaui.mjs.map +1 -0
- package/llms-full.txt +1627 -0
- package/llms.txt +60 -0
- package/package.json +251 -0
- package/styles/_fonts-entry.scss +3 -0
- package/styles/fonts/dm-mono-400-latin.woff2 +0 -0
- package/styles/fonts/inter-tight-latin-italic.woff2 +0 -0
- package/styles/fonts/inter-tight-latin.woff2 +0 -0
- package/styles/index.scss +127 -0
- package/styles/partials/_constants.scss +29 -0
- package/styles/partials/_fonts.scss +36 -0
- package/styles/partials/_grid.scss +171 -0
- package/styles/partials/_mixins.scss +145 -0
- package/styles/partials/_motion.scss +252 -0
- package/styles/partials/_theme.scss +275 -0
- package/styles/partials/_typography.scss +112 -0
- package/styles/partials/_utilities.scss +480 -0
- package/styles/partials/themes/_dark.scss +254 -0
- package/styles/partials/themes/_light.scss +254 -0
- package/types/raintonic-formaui-cdk-drag-drop.d.ts +196 -0
- package/types/raintonic-formaui-cdk-drag-drop.d.ts.map +1 -0
- package/types/raintonic-formaui-cdk-form-field.d.ts +62 -0
- package/types/raintonic-formaui-cdk-form-field.d.ts.map +1 -0
- package/types/raintonic-formaui-cdk-overlay.d.ts +843 -0
- package/types/raintonic-formaui-cdk-overlay.d.ts.map +1 -0
- package/types/raintonic-formaui-cdk-virtual-scroll.d.ts +112 -0
- package/types/raintonic-formaui-cdk-virtual-scroll.d.ts.map +1 -0
- package/types/raintonic-formaui-components-accordion.d.ts +124 -0
- package/types/raintonic-formaui-components-accordion.d.ts.map +1 -0
- package/types/raintonic-formaui-components-alert.d.ts +143 -0
- package/types/raintonic-formaui-components-alert.d.ts.map +1 -0
- package/types/raintonic-formaui-components-autocomplete.d.ts +193 -0
- package/types/raintonic-formaui-components-autocomplete.d.ts.map +1 -0
- package/types/raintonic-formaui-components-avatar.d.ts +52 -0
- package/types/raintonic-formaui-components-avatar.d.ts.map +1 -0
- package/types/raintonic-formaui-components-badge.d.ts +47 -0
- package/types/raintonic-formaui-components-badge.d.ts.map +1 -0
- package/types/raintonic-formaui-components-big-menu.d.ts +62 -0
- package/types/raintonic-formaui-components-big-menu.d.ts.map +1 -0
- package/types/raintonic-formaui-components-breadcrumb.d.ts +26 -0
- package/types/raintonic-formaui-components-breadcrumb.d.ts.map +1 -0
- package/types/raintonic-formaui-components-button-group.d.ts +61 -0
- package/types/raintonic-formaui-components-button-group.d.ts.map +1 -0
- package/types/raintonic-formaui-components-button.d.ts +116 -0
- package/types/raintonic-formaui-components-button.d.ts.map +1 -0
- package/types/raintonic-formaui-components-card.d.ts +191 -0
- package/types/raintonic-formaui-components-card.d.ts.map +1 -0
- package/types/raintonic-formaui-components-checkbox.d.ts +132 -0
- package/types/raintonic-formaui-components-checkbox.d.ts.map +1 -0
- package/types/raintonic-formaui-components-data-table.d.ts +368 -0
- package/types/raintonic-formaui-components-data-table.d.ts.map +1 -0
- package/types/raintonic-formaui-components-date-picker.d.ts +341 -0
- package/types/raintonic-formaui-components-date-picker.d.ts.map +1 -0
- package/types/raintonic-formaui-components-divider.d.ts +21 -0
- package/types/raintonic-formaui-components-divider.d.ts.map +1 -0
- package/types/raintonic-formaui-components-drawer.d.ts +48 -0
- package/types/raintonic-formaui-components-drawer.d.ts.map +1 -0
- package/types/raintonic-formaui-components-dynamic-form.d.ts +412 -0
- package/types/raintonic-formaui-components-dynamic-form.d.ts.map +1 -0
- package/types/raintonic-formaui-components-empty-state.d.ts +14 -0
- package/types/raintonic-formaui-components-empty-state.d.ts.map +1 -0
- package/types/raintonic-formaui-components-file-upload.d.ts +77 -0
- package/types/raintonic-formaui-components-file-upload.d.ts.map +1 -0
- package/types/raintonic-formaui-components-form-field.d.ts +271 -0
- package/types/raintonic-formaui-components-form-field.d.ts.map +1 -0
- package/types/raintonic-formaui-components-icon.d.ts +61 -0
- package/types/raintonic-formaui-components-icon.d.ts.map +1 -0
- package/types/raintonic-formaui-components-input.d.ts +149 -0
- package/types/raintonic-formaui-components-input.d.ts.map +1 -0
- package/types/raintonic-formaui-components-list.d.ts +48 -0
- package/types/raintonic-formaui-components-list.d.ts.map +1 -0
- package/types/raintonic-formaui-components-menu.d.ts +403 -0
- package/types/raintonic-formaui-components-menu.d.ts.map +1 -0
- package/types/raintonic-formaui-components-number-input.d.ts +127 -0
- package/types/raintonic-formaui-components-number-input.d.ts.map +1 -0
- package/types/raintonic-formaui-components-paginator.d.ts +37 -0
- package/types/raintonic-formaui-components-paginator.d.ts.map +1 -0
- package/types/raintonic-formaui-components-password-input.d.ts +111 -0
- package/types/raintonic-formaui-components-password-input.d.ts.map +1 -0
- package/types/raintonic-formaui-components-popover.d.ts +131 -0
- package/types/raintonic-formaui-components-popover.d.ts.map +1 -0
- package/types/raintonic-formaui-components-progressbar.d.ts +111 -0
- package/types/raintonic-formaui-components-progressbar.d.ts.map +1 -0
- package/types/raintonic-formaui-components-radio.d.ts +95 -0
- package/types/raintonic-formaui-components-radio.d.ts.map +1 -0
- package/types/raintonic-formaui-components-select.d.ts +307 -0
- package/types/raintonic-formaui-components-select.d.ts.map +1 -0
- package/types/raintonic-formaui-components-side-panel.d.ts +51 -0
- package/types/raintonic-formaui-components-side-panel.d.ts.map +1 -0
- package/types/raintonic-formaui-components-sidebar.d.ts +174 -0
- package/types/raintonic-formaui-components-sidebar.d.ts.map +1 -0
- package/types/raintonic-formaui-components-skeleton.d.ts +20 -0
- package/types/raintonic-formaui-components-skeleton.d.ts.map +1 -0
- package/types/raintonic-formaui-components-slider.d.ts +108 -0
- package/types/raintonic-formaui-components-slider.d.ts.map +1 -0
- package/types/raintonic-formaui-components-spinner.d.ts +42 -0
- package/types/raintonic-formaui-components-spinner.d.ts.map +1 -0
- package/types/raintonic-formaui-components-stepper.d.ts +126 -0
- package/types/raintonic-formaui-components-stepper.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tab.d.ts +96 -0
- package/types/raintonic-formaui-components-tab.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tag.d.ts +34 -0
- package/types/raintonic-formaui-components-tag.d.ts.map +1 -0
- package/types/raintonic-formaui-components-time-picker.d.ts +172 -0
- package/types/raintonic-formaui-components-time-picker.d.ts.map +1 -0
- package/types/raintonic-formaui-components-toggle.d.ts +70 -0
- package/types/raintonic-formaui-components-toggle.d.ts.map +1 -0
- package/types/raintonic-formaui-components-toolbar.d.ts +128 -0
- package/types/raintonic-formaui-components-toolbar.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tooltip.d.ts +268 -0
- package/types/raintonic-formaui-components-tooltip.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tree-select.d.ts +80 -0
- package/types/raintonic-formaui-components-tree-select.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tree-table.d.ts +90 -0
- package/types/raintonic-formaui-components-tree-table.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tree.d.ts +104 -0
- package/types/raintonic-formaui-components-tree.d.ts.map +1 -0
- package/types/raintonic-formaui-core.d.ts +115 -0
- package/types/raintonic-formaui-core.d.ts.map +1 -0
- package/types/raintonic-formaui-services-dialog.d.ts +451 -0
- package/types/raintonic-formaui-services-dialog.d.ts.map +1 -0
- package/types/raintonic-formaui-services-notification.d.ts +221 -0
- package/types/raintonic-formaui-services-notification.d.ts.map +1 -0
- package/types/raintonic-formaui-services-theme.d.ts +126 -0
- package/types/raintonic-formaui-services-theme.d.ts.map +1 -0
- package/types/raintonic-formaui-test-utils.d.ts +24 -0
- package/types/raintonic-formaui-test-utils.d.ts.map +1 -0
- package/types/raintonic-formaui.d.ts +4 -0
- package/types/raintonic-formaui.d.ts.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raintonic-formaui-components-time-picker.mjs","sources":["../../../lib/components/time-picker/time-picker.utils.ts","../../../lib/components/time-picker/time-list.component.ts","../../../lib/components/time-picker/time-list.component.html","../../../lib/components/time-picker/time-picker.component.ts","../../../lib/components/time-picker/time-picker.component.html","../../../lib/components/time-picker/raintonic-formaui-components-time-picker.ts"],"sourcesContent":["import { TimeFormat, TimeOption, TimeValue } from './time-picker.types';\n\n/**\n * Convert a TimeValue to total minutes for comparison purposes.\n */\nexport function timeToMinutes(time: TimeValue): number {\n return time.hours * 60 + time.minutes + (time.seconds ? time.seconds / 60 : 0);\n}\n\n/**\n * Compare two TimeValue objects.\n * Returns -1 if a < b, 0 if equal, 1 if a > b.\n */\nexport function compareTime(a: TimeValue, b: TimeValue): number {\n const aMin = timeToMinutes(a);\n const bMin = timeToMinutes(b);\n if (aMin < bMin) return -1;\n if (aMin > bMin) return 1;\n return 0;\n}\n\n/**\n * Check if a time is within an optional min/max range (inclusive).\n */\nexport function isTimeInRange(time: TimeValue, min?: TimeValue, max?: TimeValue): boolean {\n if (min && compareTime(time, min) < 0) return false;\n if (max && compareTime(time, max) > 0) return false;\n return true;\n}\n\n/**\n * Format a TimeValue for display.\n * - 24h: \"14:30\" or \"14:30:00\"\n * - 12h: \"2:30 PM\" or \"2:30:00 PM\"\n */\nexport function formatTime(value: TimeValue | null, format: TimeFormat, showSeconds: boolean): string {\n if (!value) return '';\n\n const h = value.hours;\n const m = value.minutes;\n const s = value.seconds ?? 0;\n\n const pad = (n: number): string => n.toString().padStart(2, '0');\n\n if (format === '24h') {\n const base = `${pad(h)}:${pad(m)}`;\n return showSeconds ? `${base}:${pad(s)}` : base;\n }\n\n // 12h format\n const period = h >= 12 ? 'PM' : 'AM';\n let displayHour = h;\n if (h === 0) displayHour = 12;\n else if (h > 12) displayHour = h - 12;\n const base = `${displayHour}:${pad(m)}`;\n return showSeconds ? `${base}:${pad(s)} ${period}` : `${base} ${period}`;\n}\n\n/**\n * Parse a time string into a TimeValue.\n * Supports formats: \"HH:mm\", \"HH:mm:ss\", \"h:mm AM/PM\", \"h:mm:ss AM/PM\"\n * Returns null if the string cannot be parsed.\n */\nexport function parseTimeString(str: string, format: TimeFormat): TimeValue | null {\n if (!str?.trim()) return null;\n\n const trimmed = str.trim();\n\n if (format === '12h') {\n // Match patterns like \"2:30 PM\", \"12:30:45 AM\"\n const match12 = /^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s*(AM|PM)$/i.exec(trimmed);\n if (!match12) return null;\n\n let hours = parseInt(match12[1], 10);\n const minutes = parseInt(match12[2], 10);\n const seconds = match12[3] ? parseInt(match12[3], 10) : undefined;\n const period = match12[4].toUpperCase();\n\n if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) return null;\n if (seconds !== undefined && (seconds < 0 || seconds > 59)) return null;\n\n if (period === 'AM' && hours === 12) hours = 0;\n else if (period === 'PM' && hours !== 12) hours += 12;\n\n return { hours, minutes, ...(seconds !== undefined ? { seconds } : {}) };\n }\n\n // 24h format: \"HH:mm\" or \"HH:mm:ss\"\n const match24 = /^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?$/.exec(trimmed);\n if (!match24) return null;\n\n const hours = parseInt(match24[1], 10);\n const minutes = parseInt(match24[2], 10);\n const seconds = match24[3] ? parseInt(match24[3], 10) : undefined;\n\n if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) return null;\n if (seconds !== undefined && (seconds < 0 || seconds > 59)) return null;\n\n return { hours, minutes, ...(seconds !== undefined ? { seconds } : {}) };\n}\n\n/**\n * Generate time options for the dropdown list.\n */\nexport function generateTimeOptions(\n format: TimeFormat,\n minuteStep: number,\n showSeconds: boolean,\n min?: TimeValue,\n max?: TimeValue,\n): TimeOption[] {\n const options: TimeOption[] = [];\n const step = Math.max(1, Math.min(60, minuteStep));\n\n for (let h = 0; h < 24; h++) {\n for (let m = 0; m < 60; m += step) {\n const value: TimeValue = { hours: h, minutes: m, ...(showSeconds ? { seconds: 0 } : {}) };\n const label = formatTime(value, format, showSeconds);\n const disabled = !isTimeInRange(value, min, max);\n options.push({ label, value, disabled });\n }\n }\n\n return options;\n}\n\n/**\n * Convert a TimeValue to an ISO-like string \"HH:mm\" or \"HH:mm:ss\".\n */\nexport function timeValueToString(value: TimeValue | null, showSeconds: boolean): string {\n if (!value) return '';\n const pad = (n: number): string => n.toString().padStart(2, '0');\n const base = `${pad(value.hours)}:${pad(value.minutes)}`;\n return showSeconds ? `${base}:${pad(value.seconds ?? 0)}` : base;\n}\n\n/**\n * Parse an ISO-like time string \"HH:mm\" or \"HH:mm:ss\" into a TimeValue.\n * This always parses in 24h format regardless of display format.\n */\nexport function parseISOTimeString(str: string): TimeValue | null {\n if (!str?.trim()) return null;\n return parseTimeString(str.trim(), '24h');\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n input,\n output,\n signal,\n ViewChild,\n ViewEncapsulation,\n AfterViewInit,\n effect,\n} from '@angular/core';\nimport { TimeFormat, TimeOption, TimeValue } from './time-picker.types';\nimport { compareTime } from './time-picker.utils';\n\n@Component({\n selector: 'fui-time-list',\n standalone: true,\n templateUrl: './time-list.component.html',\n styleUrls: ['./time-list.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-time-list',\n },\n})\nexport class FuiTimeListComponent implements AfterViewInit {\n /** The list of time options to display. */\n readonly options = input.required<TimeOption[]>();\n\n /** Currently selected time value. */\n readonly selectedValue = input<TimeValue | null>(null);\n\n /** Time format for display. */\n readonly format = input<TimeFormat>('24h');\n\n /** Emitted when an option is selected. */\n readonly optionSelected = output<TimeValue>();\n\n /** Index of the currently focused option for keyboard navigation. */\n readonly _focusedIndex = signal(-1);\n\n @ViewChild('listContainer', { static: false }) listContainer?: ElementRef<HTMLDivElement>;\n\n constructor() {\n // Scroll to selected option when options change\n effect(() => {\n this.selectedValue();\n this.options();\n // Defer to next microtask so DOM is rendered\n void Promise.resolve().then(() => {\n this._scrollToSelected();\n });\n });\n }\n\n ngAfterViewInit(): void {\n this._scrollToSelected();\n }\n\n /** Check if an option matches the selected value. */\n _isSelected(option: TimeOption): boolean {\n const selected = this.selectedValue();\n if (!selected) return false;\n return compareTime(option.value, selected) === 0;\n }\n\n /** Handle option click. */\n _selectOption(option: TimeOption): void {\n if (option.disabled) return;\n this.optionSelected.emit(option.value);\n }\n\n /** Handle keyboard navigation. */\n onKeydown(event: KeyboardEvent): void {\n const opts = this.options();\n if (!opts.length) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this._moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this._moveFocus(-1);\n break;\n case 'Enter':\n event.preventDefault();\n this._selectFocused();\n break;\n case 'Home':\n event.preventDefault();\n this._setFocusedIndex(0);\n break;\n case 'End':\n event.preventDefault();\n this._setFocusedIndex(opts.length - 1);\n break;\n }\n }\n\n /** Move focus by delta, skipping disabled options. */\n private _moveFocus(delta: number): void {\n const opts = this.options();\n if (!opts.length) return;\n\n let current = this._focusedIndex();\n const len = opts.length;\n let attempts = 0;\n\n do {\n current = (current + delta + len) % len;\n attempts++;\n } while (opts[current].disabled && attempts < len);\n\n if (!opts[current].disabled) {\n this._setFocusedIndex(current);\n }\n }\n\n /** Set focused index and scroll into view. */\n private _setFocusedIndex(index: number): void {\n this._focusedIndex.set(index);\n this._scrollToIndex(index);\n }\n\n /** Select the currently focused option. */\n private _selectFocused(): void {\n const idx = this._focusedIndex();\n const opts = this.options();\n if (idx >= 0 && idx < opts.length && !opts[idx].disabled) {\n this.optionSelected.emit(opts[idx].value);\n }\n }\n\n /** Scroll to a specific index in the list. */\n private _scrollToIndex(index: number): void {\n const container = this.listContainer?.nativeElement;\n if (!container) return;\n\n const items = container.querySelectorAll('.fui-time-list__option');\n const item = items[index] as HTMLElement;\n if (!item) return;\n\n const itemTop = item.offsetTop;\n const itemBottom = itemTop + item.offsetHeight;\n const scrollTop = container.scrollTop;\n const scrollBottom = scrollTop + container.clientHeight;\n\n if (itemTop < scrollTop) {\n container.scrollTop = itemTop;\n } else if (itemBottom > scrollBottom) {\n container.scrollTop = itemBottom - container.clientHeight;\n }\n }\n\n /** Scroll to the selected option. */\n private _scrollToSelected(): void {\n const selected = this.selectedValue();\n if (!selected) return;\n\n const opts = this.options();\n const index = opts.findIndex((o) => compareTime(o.value, selected) === 0);\n if (index >= 0) {\n this._focusedIndex.set(index);\n // Defer scroll to ensure DOM is rendered\n requestAnimationFrame(() => {\n this._scrollToIndex(index);\n });\n }\n }\n}\n","<div\n #listContainer\n class=\"fui-time-list__container\"\n role=\"listbox\"\n tabindex=\"0\"\n aria-label=\"Available times\"\n (keydown)=\"onKeydown($event)\"\n>\n @for (option of options(); track option.label) {\n <div\n class=\"fui-time-list__option\"\n [class.fui-time-list__option--selected]=\"_isSelected(option)\"\n [class.fui-time-list__option--disabled]=\"option.disabled\"\n [class.fui-time-list__option--focused]=\"_focusedIndex() === $index\"\n [attr.id]=\"'fui-time-option-' + $index\"\n [attr.aria-selected]=\"_isSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n role=\"option\"\n (click)=\"_selectOption(option)\"\n >\n {{ option.label }}\n </div>\n }\n</div>\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n DoCheck,\n effect,\n ElementRef,\n inject,\n NgZone,\n input,\n InputSignal,\n InputSignalWithTransform,\n OnDestroy,\n output,\n OutputEmitterRef,\n signal,\n ViewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { ControlValueAccessor, FormGroupDirective, NG_VALUE_ACCESSOR, NgControl, NgForm } from '@angular/forms';\nimport { DOCUMENT } from '@angular/common';\nimport { fromEvent, Subject, Subscription } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { injectNgControl, updateErrorState, syncRequiredState, syncNgControlDisabled } from '@raintonic/formaui/cdk/form-field';\nimport { FUI_FORM_FIELD_CONTROL, FuiFormFieldControl } from '@raintonic/formaui/core';\nimport { DefaultErrorStateMatcher, ErrorStateMatcher } from '@raintonic/formaui/core';\nimport { FuiConnectedPosition, FuiOverlayRef, FuiOverlayService } from '@raintonic/formaui/cdk/overlay';\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\nimport { FuiTimeListComponent } from './time-list.component';\nimport { TimeFormat, TimeOption, TimeValue } from './time-picker.types';\nimport {\n formatTime,\n generateTimeOptions,\n parseISOTimeString,\n parseTimeString,\n timeValueToString,\n} from './time-picker.utils';\n\n@Component({\n selector: 'fui-time-picker',\n standalone: true,\n imports: [FuiIconComponent, FuiTimeListComponent],\n templateUrl: './time-picker.component.html',\n styleUrls: ['./time-picker.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-time-picker',\n '[attr.id]': 'id',\n '[class.fui-time-picker--open]': '_panelOpen()',\n '[class.fui-time-picker--disabled]': 'disabled()',\n '[class.fui-time-picker--focused]': 'focused()',\n '[class.fui-time-picker--error]': 'errorState()',\n '[class.fui-time-picker--readonly]': '_readOnly()',\n },\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: FuiTimePickerComponent,\n multi: true,\n },\n {\n provide: FUI_FORM_FIELD_CONTROL,\n useExisting: FuiTimePickerComponent,\n },\n ],\n})\nexport class FuiTimePickerComponent implements ControlValueAccessor, FuiFormFieldControl<string>, DoCheck, OnDestroy {\n static nextId = 0;\n readonly controlType = 'fui-time-picker';\n\n // --- Inputs ---\n readonly formatInput: InputSignal<TimeFormat> = input<TimeFormat>('24h', { alias: 'format' });\n readonly showSeconds: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n readonly minuteStep: InputSignal<number> = input(15);\n readonly min: InputSignal<string> = input('');\n readonly max: InputSignal<string> = input('');\n readonly placeholderInput: InputSignal<string> = input('', { alias: 'placeholder' });\n readonly disabledInput: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n alias: 'disabled',\n transform: booleanAttribute,\n });\n readonly readonly: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n readonly errorStateMatcher: InputSignal<ErrorStateMatcher | null> = input<ErrorStateMatcher | null>(null);\n\n // --- Outputs ---\n readonly timeChange: OutputEmitterRef<string> = output<string>();\n\n // --- Internal state ---\n /** @internal */ readonly _value: WritableSignal<TimeValue | null> = signal(null);\n private readonly _focused: WritableSignal<boolean> = signal(false);\n private readonly _disabled: WritableSignal<boolean> = signal(false);\n private readonly _ngControlDisabled: WritableSignal<boolean> = signal(false);\n private readonly _required: WritableSignal<boolean> = signal(false);\n private readonly _errorState: WritableSignal<boolean> = signal(false);\n readonly _readOnly: WritableSignal<boolean> = signal(false);\n readonly _panelOpen = signal(false);\n\n // --- FuiFormFieldControl ---\n readonly stateChanges = new Subject<void>();\n private _uid = `fui-time-picker-${FuiTimePickerComponent.nextId++}`;\n _ariaDescribedby: string | null = null;\n\n // Form references\n private _parentForm = inject(NgForm, { optional: true });\n private _parentFormGroup = inject(FormGroupDirective, { optional: true });\n private _defaultErrorStateMatcher = inject(DefaultErrorStateMatcher);\n private readonly _ngControlRef = injectNgControl();\n get ngControl(): NgControl | null {\n return this._ngControlRef.ngControl;\n }\n\n // Interface signals\n readonly placeholder = computed(() => this.placeholderInput());\n readonly required = this._required;\n readonly value = computed(() => {\n const tv = this._value();\n return tv ? timeValueToString(tv, this.showSeconds()) : null;\n });\n readonly focused = this._focused;\n readonly disabled = computed(() => this._disabled() || this.disabledInput() || this._ngControlDisabled());\n readonly errorState = this._errorState;\n readonly id = this._uid;\n\n readonly empty = computed(() => {\n return this._value() === null;\n });\n\n // Display value formatted for current format\n readonly _displayValue = computed(() => {\n return formatTime(this._value(), this.formatInput(), this.showSeconds());\n });\n\n // Display value for form-field readOnly mode\n readonly displayValue = this._displayValue;\n\n // Computed time options for dropdown\n readonly _timeOptions = computed<TimeOption[]>(() => {\n const minVal = this.min() ? parseISOTimeString(this.min()) : undefined;\n const maxVal = this.max() ? parseISOTimeString(this.max()) : undefined;\n return generateTimeOptions(\n this.formatInput(),\n this.minuteStep(),\n this.showSeconds(),\n minVal ?? undefined,\n maxVal ?? undefined,\n );\n });\n\n // ViewChild\n @ViewChild('inputElement', { static: false }) inputElement?: ElementRef<HTMLInputElement>;\n @ViewChild('timeListPanel', { static: false }) timeListPanel?: ElementRef<HTMLDivElement>;\n\n // Overlay\n private _overlayRef: FuiOverlayRef | null = null;\n private _overlaySubscriptions = new Subscription();\n private readonly _overlayService = inject(FuiOverlayService);\n private readonly _elementRef = inject(ElementRef);\n private readonly _document = inject(DOCUMENT);\n private readonly _ngZone = inject(NgZone);\n private _outsideClickSub?: Subscription;\n\n // CVA callbacks\n private _onChange: (value: string | null) => void = () => {\n /* noop */\n };\n private _onTouched: () => void = () => {\n /* noop */\n };\n\n constructor() {\n void Promise.resolve().then(() => {\n if (this._ngControlRef.ngControl) {\n this._ngControlRef.ngControl.valueAccessor = this;\n }\n });\n\n // Effect to emit state changes\n effect(() => {\n this.placeholderInput();\n this.readonly();\n this.disabledInput();\n this.formatInput();\n this.showSeconds();\n this.minuteStep();\n this.min();\n this.max();\n this.errorStateMatcher();\n this._focused();\n this._disabled();\n this._value();\n this._ngControlDisabled();\n this._required();\n this._errorState();\n\n this.stateChanges.next();\n });\n }\n\n ngDoCheck(): void {\n if (this.ngControl) {\n updateErrorState(\n this.ngControl,\n this._errorState,\n this.errorStateMatcher(),\n this._defaultErrorStateMatcher,\n this._parentForm,\n this._parentFormGroup,\n this.stateChanges,\n );\n syncRequiredState(this.ngControl, this._required, this.stateChanges);\n syncNgControlDisabled(this.ngControl, this._ngControlDisabled, this.stateChanges);\n }\n }\n\n ngOnDestroy(): void {\n this.stateChanges.complete();\n this._outsideClickSub?.unsubscribe();\n this._disposeOverlay();\n }\n\n // --- CVA ---\n\n writeValue(value: string | null): void {\n if (value) {\n const parsed = parseISOTimeString(value);\n this._value.set(parsed);\n } else {\n this._value.set(null);\n }\n this.stateChanges.next();\n }\n\n registerOnChange(fn: (value: string | null) => void): void {\n this._onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this._onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._disabled.set(isDisabled);\n this.stateChanges.next();\n }\n\n // --- FuiFormFieldControl ---\n\n onContainerClick(_event: MouseEvent): void {\n if (!this.disabled()) {\n this.inputElement?.nativeElement.focus();\n if (!this._panelOpen()) {\n this.open();\n }\n }\n }\n\n setDescribedByIds(ids: string[]): void {\n this._ariaDescribedby = ids.length ? ids.join(' ') : null;\n }\n\n setReadOnly(readOnly: boolean): void {\n this._readOnly.set(readOnly);\n }\n\n // --- Panel open/close ---\n\n open(): void {\n if (this.disabled() || this.readonly() || this._panelOpen()) return;\n\n requestAnimationFrame(() => {\n this._panelOpen.set(true);\n this._focused.set(true);\n\n setTimeout(() => {\n this._createOverlay();\n this._listenForOutsideClicks();\n });\n });\n }\n\n close(): void {\n if (!this._panelOpen()) return;\n this._outsideClickSub?.unsubscribe();\n\n this._panelOpen.set(false);\n this._focused.set(false);\n this._disposeOverlay();\n this._onTouched();\n\n setTimeout(() => {\n this.inputElement?.nativeElement.focus();\n }, 0);\n }\n\n _togglePanel(): void {\n if (this.disabled() || this.readonly()) return;\n if (this._panelOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n // --- Event handlers ---\n\n _onManualInput(_event: Event): void {\n // We handle parsing on blur, not on every keystroke\n }\n\n _onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape' && this._panelOpen()) {\n event.preventDefault();\n this.close();\n } else if (event.key === 'ArrowDown' && !this._panelOpen()) {\n event.preventDefault();\n this.open();\n } else if (event.key === 'Enter' && !this._panelOpen()) {\n event.preventDefault();\n this.open();\n }\n }\n\n _onFocus(): void {\n this._focused.set(true);\n }\n\n _onBlur(): void {\n const input = this.inputElement?.nativeElement;\n if (!input) return;\n\n const text = input.value;\n if (!text) {\n this._setValue(null);\n return;\n }\n\n const parsed = parseTimeString(text, this.formatInput());\n if (parsed) {\n this._setValue(parsed);\n } else {\n // Invalid input — revert to previous formatted value\n input.value = this._displayValue();\n }\n\n if (!this._panelOpen()) {\n this._onTouched();\n }\n }\n\n /** Called when user selects an option from the time list dropdown. */\n _onOptionSelected(value: TimeValue): void {\n this._setValue(value);\n this.close();\n }\n\n // Start listening for outside clicks when panel opens\n private _listenForOutsideClicks(): void {\n this._outsideClickSub?.unsubscribe();\n\n this._ngZone.runOutsideAngular(() => {\n setTimeout(() => {\n this._outsideClickSub = fromEvent<MouseEvent>(this._document, 'click')\n .pipe(\n filter(() => this._panelOpen()),\n filter((event) => {\n const target = event.target as HTMLElement;\n const hostElement = this._elementRef.nativeElement;\n const overlayElement = this._overlayRef?.overlayElement;\n return !hostElement.contains(target) && !overlayElement?.contains(target);\n }),\n )\n .subscribe(() => {\n this._ngZone.run(() => {\n this.close();\n });\n });\n });\n });\n }\n\n // --- Private helpers ---\n\n private _setValue(value: TimeValue | null): void {\n this._value.set(value);\n const stringVal = value ? timeValueToString(value, this.showSeconds()) : null;\n this._onChange(stringVal);\n this.timeChange.emit(stringVal ?? '');\n this.stateChanges.next();\n }\n\n private _createOverlay(): void {\n if (this._overlayRef || !this.timeListPanel) return;\n\n const triggerElement = this._elementRef.nativeElement;\n const triggerWidth = triggerElement.getBoundingClientRect().width;\n\n const positions: FuiConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },\n ];\n\n const positionStrategy = this._overlayService\n .position()\n .connectedTo(triggerElement, positions)\n .withPush(true)\n .withViewportMargin(8);\n\n this._overlayRef = this._overlayService.create({\n positionStrategy,\n scrollStrategy: this._overlayService.scrollStrategies.reposition(),\n hasBackdrop: true,\n backdropClass: 'fui-time-picker-backdrop',\n backdropClickBehavior: 'close',\n panelClass: ['fui-time-picker-overlay-panel'],\n minWidth: Math.max(triggerWidth, 160),\n });\n\n // Track overlay subscriptions for proper cleanup\n this._overlaySubscriptions.unsubscribe();\n this._overlaySubscriptions = new Subscription();\n\n this._overlaySubscriptions.add(\n this._overlayRef.backdropClick.subscribe(() => {\n this.close();\n }),\n );\n\n this._overlaySubscriptions.add(\n this._overlayRef.keydownEvents.subscribe((event) => {\n if (event.key === 'Escape') {\n this.close();\n }\n }),\n );\n\n const panelElement = this.timeListPanel.nativeElement;\n this._overlayRef.attach(panelElement);\n }\n\n private _disposeOverlay(): void {\n this._overlaySubscriptions.unsubscribe();\n if (this._overlayRef) {\n this._overlayRef.dispose();\n this._overlayRef = null;\n }\n }\n}\n","<div class=\"fui-time-picker__wrapper\">\n <input\n #inputElement\n class=\"fui-time-picker__input\"\n type=\"text\"\n [attr.placeholder]=\"placeholder()\"\n [attr.disabled]=\"disabled() ? '' : null\"\n [attr.readonly]=\"readonly() ? '' : null\"\n [value]=\"_displayValue()\"\n [attr.aria-expanded]=\"_panelOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-describedby]=\"_ariaDescribedby\"\n [attr.aria-required]=\"required()\"\n [attr.aria-invalid]=\"errorState()\"\n role=\"combobox\"\n autocomplete=\"off\"\n (input)=\"_onManualInput($event)\"\n (keydown)=\"_onKeydown($event)\"\n (focus)=\"_onFocus()\"\n (blur)=\"_onBlur()\"\n />\n @if (!_readOnly()) {\n <button\n type=\"button\"\n class=\"fui-time-picker__toggle\"\n (click)=\"_togglePanel()\"\n [disabled]=\"disabled() || readonly()\"\n tabindex=\"-1\"\n aria-label=\"Toggle time picker\"\n >\n <fui-icon name=\"clock\" size=\"sm\"></fui-icon>\n </button>\n }\n</div>\n\n@if (_panelOpen()) {\n <div #timeListPanel class=\"fui-time-picker__panel\" role=\"dialog\" aria-label=\"Time selection\">\n <fui-time-list\n [options]=\"_timeOptions()\"\n [selectedValue]=\"_value()\"\n [format]=\"formatInput()\"\n (optionSelected)=\"_onOptionSelected($event)\"\n />\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, booleanAttribute, output, signal, computed, inject, viewChild, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { NgForm, FormGroupDirective, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import { Subject } from 'rxjs';
|
|
5
|
+
import { DefaultErrorStateMatcher } from '@raintonic/formaui/core';
|
|
6
|
+
import { injectNgControl, updateErrorState, syncRequiredState, syncNgControlDisabled } from '@raintonic/formaui/cdk/form-field';
|
|
7
|
+
|
|
8
|
+
class FuiToggleComponent {
|
|
9
|
+
static nextId = 0;
|
|
10
|
+
controlType = 'fui-toggle';
|
|
11
|
+
// Inputs
|
|
12
|
+
checkedInput = input(false, { ...(ngDevMode ? { debugName: "checkedInput" } : /* istanbul ignore next */ {}), alias: 'checked', transform: booleanAttribute });
|
|
13
|
+
disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled', transform: booleanAttribute });
|
|
14
|
+
requiredInput = input(false, { ...(ngDevMode ? { debugName: "requiredInput" } : /* istanbul ignore next */ {}), alias: 'required', transform: booleanAttribute });
|
|
15
|
+
labelPosition = input('after', ...(ngDevMode ? [{ debugName: "labelPosition" }] : /* istanbul ignore next */ []));
|
|
16
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
17
|
+
name = input(null, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
18
|
+
ariaLabel = input(null, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
19
|
+
ariaLabelledby = input(null, { ...(ngDevMode ? { debugName: "ariaLabelledby" } : /* istanbul ignore next */ {}), alias: 'aria-labelledby' });
|
|
20
|
+
ariaDescribedby = input(null, { ...(ngDevMode ? { debugName: "ariaDescribedby" } : /* istanbul ignore next */ {}), alias: 'aria-describedby' });
|
|
21
|
+
errorStateMatcher = input(null, ...(ngDevMode ? [{ debugName: "errorStateMatcher" }] : /* istanbul ignore next */ []));
|
|
22
|
+
// Outputs
|
|
23
|
+
change = output();
|
|
24
|
+
// Internal state
|
|
25
|
+
_checked = signal(false, ...(ngDevMode ? [{ debugName: "_checked" }] : /* istanbul ignore next */ []));
|
|
26
|
+
_focused = signal(false, ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
|
|
27
|
+
_disabled = signal(false, ...(ngDevMode ? [{ debugName: "_disabled" }] : /* istanbul ignore next */ []));
|
|
28
|
+
_required = signal(false, ...(ngDevMode ? [{ debugName: "_required" }] : /* istanbul ignore next */ []));
|
|
29
|
+
_ngControlDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_ngControlDisabled" }] : /* istanbul ignore next */ []));
|
|
30
|
+
_errorState = signal(false, ...(ngDevMode ? [{ debugName: "_errorState" }] : /* istanbul ignore next */ []));
|
|
31
|
+
// Public readonly signals
|
|
32
|
+
checked = this._checked.asReadonly();
|
|
33
|
+
focused = this._focused.asReadonly();
|
|
34
|
+
errorState = this._errorState.asReadonly();
|
|
35
|
+
required = computed(() => this._required() || this.requiredInput(), ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
36
|
+
disabled = computed(() => this._disabled() || this.disabledInput() || this._ngControlDisabled(), ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
37
|
+
stateChanges = new Subject();
|
|
38
|
+
_uid = `fui-toggle-${FuiToggleComponent.nextId++}`;
|
|
39
|
+
id = this._uid;
|
|
40
|
+
inputId = `${this._uid}-input`;
|
|
41
|
+
// Form control
|
|
42
|
+
_parentForm = inject(NgForm, { optional: true });
|
|
43
|
+
_parentFormGroup = inject(FormGroupDirective, { optional: true });
|
|
44
|
+
_defaultErrorStateMatcher = inject(DefaultErrorStateMatcher);
|
|
45
|
+
_ngControlRef = injectNgControl();
|
|
46
|
+
get ngControl() {
|
|
47
|
+
return this._ngControlRef.ngControl;
|
|
48
|
+
}
|
|
49
|
+
inputElement = viewChild('inputElement', ...(ngDevMode ? [{ debugName: "inputElement" }] : /* istanbul ignore next */ []));
|
|
50
|
+
_onChange = () => {
|
|
51
|
+
/* noop */
|
|
52
|
+
};
|
|
53
|
+
_onTouched = () => {
|
|
54
|
+
/* noop */
|
|
55
|
+
};
|
|
56
|
+
_formControlInitialized = false;
|
|
57
|
+
constructor() {
|
|
58
|
+
void Promise.resolve().then(() => {
|
|
59
|
+
if (this._ngControlRef.ngControl) {
|
|
60
|
+
this._ngControlRef.ngControl.valueAccessor = this;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
effect(() => {
|
|
64
|
+
const inputChecked = this.checkedInput();
|
|
65
|
+
if (!this._formControlInitialized) {
|
|
66
|
+
this._checked.set(inputChecked);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
effect(() => {
|
|
70
|
+
this.checkedInput();
|
|
71
|
+
this.disabledInput();
|
|
72
|
+
this.requiredInput();
|
|
73
|
+
this.labelPosition();
|
|
74
|
+
this.size();
|
|
75
|
+
this.name();
|
|
76
|
+
this._checked();
|
|
77
|
+
this._focused();
|
|
78
|
+
this._disabled();
|
|
79
|
+
this._ngControlDisabled();
|
|
80
|
+
this._required();
|
|
81
|
+
this._errorState();
|
|
82
|
+
this.stateChanges.next();
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
ngDoCheck() {
|
|
86
|
+
if (this.ngControl) {
|
|
87
|
+
updateErrorState(this.ngControl, this._errorState, this.errorStateMatcher(), this._defaultErrorStateMatcher, this._parentForm, this._parentFormGroup, this.stateChanges);
|
|
88
|
+
syncRequiredState(this.ngControl, this._required, this.stateChanges);
|
|
89
|
+
syncNgControlDisabled(this.ngControl, this._ngControlDisabled, this.stateChanges);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
ngOnDestroy() {
|
|
93
|
+
this.stateChanges.complete();
|
|
94
|
+
}
|
|
95
|
+
// CVA
|
|
96
|
+
writeValue(value) {
|
|
97
|
+
this._formControlInitialized = true;
|
|
98
|
+
this._checked.set(value);
|
|
99
|
+
this.stateChanges.next();
|
|
100
|
+
}
|
|
101
|
+
registerOnChange(fn) {
|
|
102
|
+
this._onChange = fn;
|
|
103
|
+
}
|
|
104
|
+
registerOnTouched(fn) {
|
|
105
|
+
this._onTouched = fn;
|
|
106
|
+
}
|
|
107
|
+
setDisabledState(isDisabled) {
|
|
108
|
+
this._disabled.set(isDisabled);
|
|
109
|
+
this.stateChanges.next();
|
|
110
|
+
}
|
|
111
|
+
// Event handlers
|
|
112
|
+
onInputChange(event) {
|
|
113
|
+
event.stopPropagation();
|
|
114
|
+
if (this.disabled())
|
|
115
|
+
return;
|
|
116
|
+
const newChecked = !this._checked();
|
|
117
|
+
this._checked.set(newChecked);
|
|
118
|
+
this._onChange(newChecked);
|
|
119
|
+
this.change.emit({ source: this, checked: newChecked });
|
|
120
|
+
this.stateChanges.next();
|
|
121
|
+
}
|
|
122
|
+
onFocus() {
|
|
123
|
+
if (!this._focused()) {
|
|
124
|
+
this._focused.set(true);
|
|
125
|
+
this.stateChanges.next();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
onBlur() {
|
|
129
|
+
if (this._focused()) {
|
|
130
|
+
this._focused.set(false);
|
|
131
|
+
this._onTouched();
|
|
132
|
+
this.stateChanges.next();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
toggle() {
|
|
136
|
+
if (!this.disabled()) {
|
|
137
|
+
const newChecked = !this._checked();
|
|
138
|
+
this._checked.set(newChecked);
|
|
139
|
+
this._onChange(newChecked);
|
|
140
|
+
this.change.emit({ source: this, checked: newChecked });
|
|
141
|
+
this.stateChanges.next();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
focus() {
|
|
145
|
+
this.inputElement()?.nativeElement.focus();
|
|
146
|
+
}
|
|
147
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
148
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiToggleComponent, isStandalone: true, selector: "fui-toggle", inputs: { checkedInput: { classPropertyName: "checkedInput", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, requiredInput: { classPropertyName: "requiredInput", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "aria-describedby", isSignal: true, isRequired: false, transformFunction: null }, errorStateMatcher: { classPropertyName: "errorStateMatcher", publicName: "errorStateMatcher", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change" }, host: { properties: { "class.fui-toggle--checked": "checked()", "class.fui-toggle--disabled": "disabled()", "class.fui-toggle--focused": "focused()", "class.fui-toggle--sm": "size() === \"sm\"", "class.fui-toggle--md": "size() === \"md\"", "class.fui-toggle--label-before": "labelPosition() === \"before\"", "class.fui-toggle--error": "errorState()", "attr.id": "id", "attr.tabindex": "null" }, classAttribute: "fui-toggle" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: FuiToggleComponent, multi: true }], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true, isSignal: true }], ngImport: i0, template: "<label class=\"fui-toggle__container\" [attr.for]=\"inputId\">\r\n @if (labelPosition() === 'before') {\r\n <span class=\"fui-toggle__label fui-toggle__label--before\">\r\n <ng-content></ng-content>\r\n </span>\r\n }\r\n\r\n <span class=\"fui-toggle__track\">\r\n <input\r\n #inputElement\r\n type=\"checkbox\"\r\n role=\"switch\"\r\n class=\"fui-toggle__native-control\"\r\n [id]=\"inputId\"\r\n [name]=\"name()\"\r\n [checked]=\"checked()\"\r\n [disabled]=\"disabled()\"\r\n [required]=\"required()\"\r\n [attr.aria-checked]=\"checked()\"\r\n [attr.aria-label]=\"ariaLabel()\"\r\n [attr.aria-labelledby]=\"ariaLabelledby()\"\r\n [attr.aria-describedby]=\"ariaDescribedby()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-required]=\"required()\"\r\n (change)=\"onInputChange($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n />\r\n <span class=\"fui-toggle__thumb\"></span>\r\n </span>\r\n\r\n @if (labelPosition() === 'after') {\r\n <span class=\"fui-toggle__label fui-toggle__label--after\">\r\n <ng-content></ng-content>\r\n </span>\r\n }\r\n</label>\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-toggle{display:inline-flex;align-items:center}.fui-toggle__container{display:inline-flex;align-items:center;gap:var(--fui-gap-12, .75rem);cursor:pointer}.fui-toggle__track{position:relative;width:2.75rem;height:1.5rem;border-radius:var(--fui-border-radius-pill, 999px);background-color:var(--fui-secondary-60, #94a3b8);transition:background-color var(--fui-duration-fast-02, .15s) var(--fui-ease-standard) 0ms}.fui-toggle__native-control{position:absolute;width:100%;height:100%;margin:0;padding:0;opacity:0;cursor:inherit;z-index:1}.fui-toggle__track:has(.fui-toggle__native-control:focus-visible){outline:2px solid var(--fui-primary);outline-offset:2px}.fui-toggle__thumb{position:absolute;top:50%;left:3px;width:1.125rem;height:1.125rem;border-radius:50%;background-color:#fff;transform:translateY(-50%);transition:left var(--fui-duration-fast-02, .15s) var(--fui-ease-standard, cubic-bezier(.4, 0, .2, 1)) 0ms;pointer-events:none}.fui-toggle--checked .fui-toggle__track{background-color:var(--fui-primary)}.fui-toggle--checked .fui-toggle__thumb{left:calc(100% - 1.125rem - 3px)}.fui-toggle--sm .fui-toggle__track{width:2rem;height:1.125rem}.fui-toggle--sm .fui-toggle__thumb{width:.875rem;height:.875rem}.fui-toggle--sm.fui-toggle--checked .fui-toggle__thumb{left:calc(100% - .875rem - 3px)}.fui-toggle--disabled{cursor:not-allowed;opacity:var(--fui-opacity-disabled, .38)}.fui-toggle--disabled .fui-toggle__container{cursor:not-allowed}.fui-toggle--error .fui-toggle__track{background-color:var(--fui-state-error)}.fui-toggle__label{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-primary);-webkit-user-select:none;user-select:none}.fui-toggle--label-before .fui-toggle__container{flex-direction:row-reverse}@media(prefers-contrast:high){.fui-toggle__track{border:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fui-toggle__thumb,.fui-toggle__track{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
149
|
+
}
|
|
150
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiToggleComponent, decorators: [{
|
|
151
|
+
type: Component,
|
|
152
|
+
args: [{ selector: 'fui-toggle', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
153
|
+
class: 'fui-toggle',
|
|
154
|
+
'[class.fui-toggle--checked]': 'checked()',
|
|
155
|
+
'[class.fui-toggle--disabled]': 'disabled()',
|
|
156
|
+
'[class.fui-toggle--focused]': 'focused()',
|
|
157
|
+
'[class.fui-toggle--sm]': 'size() === "sm"',
|
|
158
|
+
'[class.fui-toggle--md]': 'size() === "md"',
|
|
159
|
+
'[class.fui-toggle--label-before]': 'labelPosition() === "before"',
|
|
160
|
+
'[class.fui-toggle--error]': 'errorState()',
|
|
161
|
+
'[attr.id]': 'id',
|
|
162
|
+
'[attr.tabindex]': 'null',
|
|
163
|
+
}, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: FuiToggleComponent, multi: true }], template: "<label class=\"fui-toggle__container\" [attr.for]=\"inputId\">\r\n @if (labelPosition() === 'before') {\r\n <span class=\"fui-toggle__label fui-toggle__label--before\">\r\n <ng-content></ng-content>\r\n </span>\r\n }\r\n\r\n <span class=\"fui-toggle__track\">\r\n <input\r\n #inputElement\r\n type=\"checkbox\"\r\n role=\"switch\"\r\n class=\"fui-toggle__native-control\"\r\n [id]=\"inputId\"\r\n [name]=\"name()\"\r\n [checked]=\"checked()\"\r\n [disabled]=\"disabled()\"\r\n [required]=\"required()\"\r\n [attr.aria-checked]=\"checked()\"\r\n [attr.aria-label]=\"ariaLabel()\"\r\n [attr.aria-labelledby]=\"ariaLabelledby()\"\r\n [attr.aria-describedby]=\"ariaDescribedby()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-required]=\"required()\"\r\n (change)=\"onInputChange($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n />\r\n <span class=\"fui-toggle__thumb\"></span>\r\n </span>\r\n\r\n @if (labelPosition() === 'after') {\r\n <span class=\"fui-toggle__label fui-toggle__label--after\">\r\n <ng-content></ng-content>\r\n </span>\r\n }\r\n</label>\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-toggle{display:inline-flex;align-items:center}.fui-toggle__container{display:inline-flex;align-items:center;gap:var(--fui-gap-12, .75rem);cursor:pointer}.fui-toggle__track{position:relative;width:2.75rem;height:1.5rem;border-radius:var(--fui-border-radius-pill, 999px);background-color:var(--fui-secondary-60, #94a3b8);transition:background-color var(--fui-duration-fast-02, .15s) var(--fui-ease-standard) 0ms}.fui-toggle__native-control{position:absolute;width:100%;height:100%;margin:0;padding:0;opacity:0;cursor:inherit;z-index:1}.fui-toggle__track:has(.fui-toggle__native-control:focus-visible){outline:2px solid var(--fui-primary);outline-offset:2px}.fui-toggle__thumb{position:absolute;top:50%;left:3px;width:1.125rem;height:1.125rem;border-radius:50%;background-color:#fff;transform:translateY(-50%);transition:left var(--fui-duration-fast-02, .15s) var(--fui-ease-standard, cubic-bezier(.4, 0, .2, 1)) 0ms;pointer-events:none}.fui-toggle--checked .fui-toggle__track{background-color:var(--fui-primary)}.fui-toggle--checked .fui-toggle__thumb{left:calc(100% - 1.125rem - 3px)}.fui-toggle--sm .fui-toggle__track{width:2rem;height:1.125rem}.fui-toggle--sm .fui-toggle__thumb{width:.875rem;height:.875rem}.fui-toggle--sm.fui-toggle--checked .fui-toggle__thumb{left:calc(100% - .875rem - 3px)}.fui-toggle--disabled{cursor:not-allowed;opacity:var(--fui-opacity-disabled, .38)}.fui-toggle--disabled .fui-toggle__container{cursor:not-allowed}.fui-toggle--error .fui-toggle__track{background-color:var(--fui-state-error)}.fui-toggle__label{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-primary);-webkit-user-select:none;user-select:none}.fui-toggle--label-before .fui-toggle__container{flex-direction:row-reverse}@media(prefers-contrast:high){.fui-toggle__track{border:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fui-toggle__thumb,.fui-toggle__track{transition:none}}\n"] }]
|
|
164
|
+
}], ctorParameters: () => [], propDecorators: { checkedInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], requiredInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-describedby", required: false }] }], errorStateMatcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStateMatcher", required: false }] }], change: [{ type: i0.Output, args: ["change"] }], inputElement: [{ type: i0.ViewChild, args: ['inputElement', { isSignal: true }] }] } });
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Generated bundle index. Do not edit.
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
export { FuiToggleComponent };
|
|
171
|
+
//# sourceMappingURL=raintonic-formaui-components-toggle.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raintonic-formaui-components-toggle.mjs","sources":["../../../lib/components/toggle/toggle.component.ts","../../../lib/components/toggle/toggle.component.html","../../../lib/components/toggle/raintonic-formaui-components-toggle.ts"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n input,\n output,\n computed,\n signal,\n viewChild,\n ElementRef,\n OutputEmitterRef,\n Signal,\n WritableSignal,\n OnDestroy,\n DoCheck,\n inject,\n effect,\n booleanAttribute,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR, NgControl, FormGroupDirective, NgForm } from '@angular/forms';\nimport { Subject } from 'rxjs';\nimport { DefaultErrorStateMatcher, ErrorStateMatcher } from '@raintonic/formaui/core';\nimport { injectNgControl, updateErrorState, syncRequiredState, syncNgControlDisabled } from '@raintonic/formaui/cdk/form-field';\nimport { FuiToggleLabelPosition, FuiToggleSize, FuiToggleChange } from './toggle.types';\n\n@Component({\n selector: 'fui-toggle',\n standalone: true,\n imports: [],\n templateUrl: './toggle.component.html',\n styleUrls: ['./toggle.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-toggle',\n '[class.fui-toggle--checked]': 'checked()',\n '[class.fui-toggle--disabled]': 'disabled()',\n '[class.fui-toggle--focused]': 'focused()',\n '[class.fui-toggle--sm]': 'size() === \"sm\"',\n '[class.fui-toggle--md]': 'size() === \"md\"',\n '[class.fui-toggle--label-before]': 'labelPosition() === \"before\"',\n '[class.fui-toggle--error]': 'errorState()',\n '[attr.id]': 'id',\n '[attr.tabindex]': 'null',\n },\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: FuiToggleComponent, multi: true }],\n})\nexport class FuiToggleComponent implements ControlValueAccessor, DoCheck, OnDestroy {\n static nextId = 0;\n readonly controlType = 'fui-toggle';\n\n // Inputs\n readonly checkedInput = input<boolean, unknown>(false, { alias: 'checked', transform: booleanAttribute });\n readonly disabledInput = input<boolean, unknown>(false, { alias: 'disabled', transform: booleanAttribute });\n readonly requiredInput = input<boolean, unknown>(false, { alias: 'required', transform: booleanAttribute });\n readonly labelPosition = input<FuiToggleLabelPosition>('after');\n readonly size = input<FuiToggleSize>('md');\n readonly name = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null, { alias: 'aria-label' });\n readonly ariaLabelledby = input<string | null>(null, { alias: 'aria-labelledby' });\n readonly ariaDescribedby = input<string | null>(null, { alias: 'aria-describedby' });\n readonly errorStateMatcher = input<ErrorStateMatcher | null>(null);\n\n // Outputs\n readonly change: OutputEmitterRef<FuiToggleChange> = output<FuiToggleChange>();\n\n // Internal state\n private readonly _checked: WritableSignal<boolean> = signal(false);\n private readonly _focused: WritableSignal<boolean> = signal(false);\n private readonly _disabled: WritableSignal<boolean> = signal(false);\n private readonly _required: WritableSignal<boolean> = signal(false);\n private readonly _ngControlDisabled: WritableSignal<boolean> = signal(false);\n private readonly _errorState: WritableSignal<boolean> = signal(false);\n\n // Public readonly signals\n readonly checked: Signal<boolean> = this._checked.asReadonly();\n readonly focused: Signal<boolean> = this._focused.asReadonly();\n readonly errorState = this._errorState.asReadonly();\n readonly required: Signal<boolean> = computed(() => this._required() || this.requiredInput());\n readonly disabled: Signal<boolean> = computed(\n () => this._disabled() || this.disabledInput() || this._ngControlDisabled(),\n );\n\n readonly stateChanges = new Subject<void>();\n private _uid = `fui-toggle-${FuiToggleComponent.nextId++}`;\n readonly id = this._uid;\n readonly inputId = `${this._uid}-input`;\n\n // Form control\n private _parentForm = inject(NgForm, { optional: true });\n private _parentFormGroup = inject(FormGroupDirective, { optional: true });\n private _defaultErrorStateMatcher = inject(DefaultErrorStateMatcher);\n private readonly _ngControlRef = injectNgControl();\n get ngControl(): NgControl | null {\n return this._ngControlRef.ngControl;\n }\n\n readonly inputElement: Signal<ElementRef<HTMLInputElement> | undefined> =\n viewChild<ElementRef<HTMLInputElement>>('inputElement');\n\n private _onChange: (value: boolean) => void = () => {\n /* noop */\n };\n private _onTouched: () => void = () => {\n /* noop */\n };\n private _formControlInitialized = false;\n\n constructor() {\n void Promise.resolve().then(() => {\n if (this._ngControlRef.ngControl) {\n this._ngControlRef.ngControl.valueAccessor = this;\n }\n });\n\n effect(() => {\n const inputChecked = this.checkedInput();\n if (!this._formControlInitialized) {\n this._checked.set(inputChecked);\n }\n });\n\n effect(() => {\n this.checkedInput();\n this.disabledInput();\n this.requiredInput();\n this.labelPosition();\n this.size();\n this.name();\n this._checked();\n this._focused();\n this._disabled();\n this._ngControlDisabled();\n this._required();\n this._errorState();\n this.stateChanges.next();\n });\n }\n\n ngDoCheck(): void {\n if (this.ngControl) {\n updateErrorState(\n this.ngControl,\n this._errorState,\n this.errorStateMatcher(),\n this._defaultErrorStateMatcher,\n this._parentForm,\n this._parentFormGroup,\n this.stateChanges,\n );\n syncRequiredState(this.ngControl, this._required, this.stateChanges);\n syncNgControlDisabled(this.ngControl, this._ngControlDisabled, this.stateChanges);\n }\n }\n\n ngOnDestroy(): void {\n this.stateChanges.complete();\n }\n\n // CVA\n writeValue(value: boolean): void {\n this._formControlInitialized = true;\n this._checked.set(value);\n this.stateChanges.next();\n }\n registerOnChange(fn: (value: boolean) => void): void {\n this._onChange = fn;\n }\n registerOnTouched(fn: () => void): void {\n this._onTouched = fn;\n }\n setDisabledState(isDisabled: boolean): void {\n this._disabled.set(isDisabled);\n this.stateChanges.next();\n }\n\n // Event handlers\n onInputChange(event: Event): void {\n event.stopPropagation();\n if (this.disabled()) return;\n const newChecked = !this._checked();\n this._checked.set(newChecked);\n this._onChange(newChecked);\n this.change.emit({ source: this, checked: newChecked });\n this.stateChanges.next();\n }\n\n onFocus(): void {\n if (!this._focused()) {\n this._focused.set(true);\n this.stateChanges.next();\n }\n }\n\n onBlur(): void {\n if (this._focused()) {\n this._focused.set(false);\n this._onTouched();\n this.stateChanges.next();\n }\n }\n\n toggle(): void {\n if (!this.disabled()) {\n const newChecked = !this._checked();\n this._checked.set(newChecked);\n this._onChange(newChecked);\n this.change.emit({ source: this, checked: newChecked });\n this.stateChanges.next();\n }\n }\n\n focus(): void {\n this.inputElement()?.nativeElement.focus();\n }\n}\n","<label class=\"fui-toggle__container\" [attr.for]=\"inputId\">\r\n @if (labelPosition() === 'before') {\r\n <span class=\"fui-toggle__label fui-toggle__label--before\">\r\n <ng-content></ng-content>\r\n </span>\r\n }\r\n\r\n <span class=\"fui-toggle__track\">\r\n <input\r\n #inputElement\r\n type=\"checkbox\"\r\n role=\"switch\"\r\n class=\"fui-toggle__native-control\"\r\n [id]=\"inputId\"\r\n [name]=\"name()\"\r\n [checked]=\"checked()\"\r\n [disabled]=\"disabled()\"\r\n [required]=\"required()\"\r\n [attr.aria-checked]=\"checked()\"\r\n [attr.aria-label]=\"ariaLabel()\"\r\n [attr.aria-labelledby]=\"ariaLabelledby()\"\r\n [attr.aria-describedby]=\"ariaDescribedby()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-required]=\"required()\"\r\n (change)=\"onInputChange($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n />\r\n <span class=\"fui-toggle__thumb\"></span>\r\n </span>\r\n\r\n @if (labelPosition() === 'after') {\r\n <span class=\"fui-toggle__label fui-toggle__label--after\">\r\n <ng-content></ng-content>\r\n </span>\r\n }\r\n</label>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, output, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/router';
|
|
4
|
+
import { RouterModule } from '@angular/router';
|
|
5
|
+
import { FuiIconComponent } from '@raintonic/formaui/components/icon';
|
|
6
|
+
import { FuiAvatarComponent } from '@raintonic/formaui/components/avatar';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* # FuiToolbar Component
|
|
10
|
+
*
|
|
11
|
+
* A top navigation toolbar following Carbon Design System principles.
|
|
12
|
+
* Provides space for logo, navigation menu items, and user profile area.
|
|
13
|
+
*
|
|
14
|
+
* ## Features
|
|
15
|
+
* - Logo area with customizable content
|
|
16
|
+
* - Icon-based navigation menu
|
|
17
|
+
* - User profile area with avatar/initials
|
|
18
|
+
* - Responsive design
|
|
19
|
+
* - Theme integration
|
|
20
|
+
* - Accessibility support
|
|
21
|
+
*
|
|
22
|
+
* ## Usage
|
|
23
|
+
*
|
|
24
|
+
* ### Basic Toolbar
|
|
25
|
+
* ```html
|
|
26
|
+
* <fui-toolbar
|
|
27
|
+
* [menuItems]="menuItems"
|
|
28
|
+
* [userProfile]="userProfile"
|
|
29
|
+
* (menuItemClick)="onMenuItemClick($event)"
|
|
30
|
+
* (userProfileClick)="onUserProfileClick()">
|
|
31
|
+
* <div logo>
|
|
32
|
+
* <img src="logo.svg" alt="Company Logo">
|
|
33
|
+
* </div>
|
|
34
|
+
* </fui-toolbar>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* ### With Custom Logo
|
|
38
|
+
* ```html
|
|
39
|
+
* <fui-toolbar [menuItems]="menuItems" [userProfile]="userProfile">
|
|
40
|
+
* <div logo class="custom-logo">
|
|
41
|
+
* <h1>Holiday ERP</h1>
|
|
42
|
+
* </div>
|
|
43
|
+
* </fui-toolbar>
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { FuiToolbarComponent, FuiToolbarMenuItem, FuiToolbarUserProfile } from '@raintonic/formaui/components/toolbar';
|
|
49
|
+
*
|
|
50
|
+
* @Component({
|
|
51
|
+
* standalone: true,
|
|
52
|
+
* imports: [FuiToolbarComponent],
|
|
53
|
+
* template: `
|
|
54
|
+
* <fui-toolbar
|
|
55
|
+
* [menuItems]="menuItems"
|
|
56
|
+
* [userProfile]="userProfile"
|
|
57
|
+
* (menuItemClick)="onMenuItemClick($event)"
|
|
58
|
+
* (userProfileClick)="onUserProfileClick()">
|
|
59
|
+
* <div logo>
|
|
60
|
+
* <img src="assets/logo.svg" alt="Holiday ERP">
|
|
61
|
+
* </div>
|
|
62
|
+
* </fui-toolbar>
|
|
63
|
+
* `
|
|
64
|
+
* })
|
|
65
|
+
* export class AppLayoutComponent {
|
|
66
|
+
* menuItems: FuiToolbarMenuItem[] = [
|
|
67
|
+
* { id: 'dashboard', icon: 'house', label: 'Dashboard' },
|
|
68
|
+
* { id: 'orders', icon: 'shopping-cart', label: 'Orders' },
|
|
69
|
+
* { id: 'products', icon: 'package', label: 'Products' },
|
|
70
|
+
* { id: 'customers', icon: 'users', label: 'Customers' },
|
|
71
|
+
* ];
|
|
72
|
+
*
|
|
73
|
+
* userProfile: FuiToolbarUserProfile = {
|
|
74
|
+
* name: 'John Doe',
|
|
75
|
+
* email: 'john.doe@company.com',
|
|
76
|
+
* initials: 'JD'
|
|
77
|
+
* };
|
|
78
|
+
*
|
|
79
|
+
* onMenuItemClick(itemId: string | number): void {
|
|
80
|
+
* console.log('Menu item clicked:', itemId);
|
|
81
|
+
* }
|
|
82
|
+
*
|
|
83
|
+
* onUserProfileClick(): void {
|
|
84
|
+
* console.log('User profile clicked');
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
class FuiToolbarComponent {
|
|
90
|
+
// Inputs using signal-based API
|
|
91
|
+
menuItems = input([], ...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
92
|
+
userProfile = input(null, ...(ngDevMode ? [{ debugName: "userProfile" }] : /* istanbul ignore next */ []));
|
|
93
|
+
fixed = input(true, ...(ngDevMode ? [{ debugName: "fixed" }] : /* istanbul ignore next */ []));
|
|
94
|
+
activeMenuItemId = input('', ...(ngDevMode ? [{ debugName: "activeMenuItemId" }] : /* istanbul ignore next */ []));
|
|
95
|
+
ariaLabel = input('Main navigation', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
96
|
+
userAriaLabel = input('User menu for ', ...(ngDevMode ? [{ debugName: "userAriaLabel" }] : /* istanbul ignore next */ []));
|
|
97
|
+
// New: show a dedicated sidebar toggle button
|
|
98
|
+
showSidebarToggle = input(false, ...(ngDevMode ? [{ debugName: "showSidebarToggle" }] : /* istanbul ignore next */ []));
|
|
99
|
+
// Outputs using signal-based API
|
|
100
|
+
menuItemClick = output();
|
|
101
|
+
userProfileClick = output();
|
|
102
|
+
// New: emits when sidebar toggle button is clicked
|
|
103
|
+
sidebarToggle = output();
|
|
104
|
+
// Derived user name parts for avatar
|
|
105
|
+
firstName = computed(() => this.userProfile()?.name?.trim().split(/\s+/)[0] ?? '', ...(ngDevMode ? [{ debugName: "firstName" }] : /* istanbul ignore next */ []));
|
|
106
|
+
lastName = computed(() => {
|
|
107
|
+
const parts = this.userProfile()?.name?.trim().split(/\s+/) ?? [];
|
|
108
|
+
return parts.length > 1 ? parts[parts.length - 1] : '';
|
|
109
|
+
}, ...(ngDevMode ? [{ debugName: "lastName" }] : /* istanbul ignore next */ []));
|
|
110
|
+
onMenuItemClick(item) {
|
|
111
|
+
if (!item.disabled) {
|
|
112
|
+
this.menuItemClick.emit(item.id);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
onUserProfileClick() {
|
|
116
|
+
if (this.userProfile()) {
|
|
117
|
+
this.userProfileClick.emit();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
onSidebarToggleClick() {
|
|
121
|
+
this.sidebarToggle.emit();
|
|
122
|
+
}
|
|
123
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
124
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiToolbarComponent, isStandalone: true, selector: "fui-toolbar", inputs: { menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: false, transformFunction: null }, userProfile: { classPropertyName: "userProfile", publicName: "userProfile", isSignal: true, isRequired: false, transformFunction: null }, fixed: { classPropertyName: "fixed", publicName: "fixed", isSignal: true, isRequired: false, transformFunction: null }, activeMenuItemId: { classPropertyName: "activeMenuItemId", publicName: "activeMenuItemId", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, userAriaLabel: { classPropertyName: "userAriaLabel", publicName: "userAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, showSidebarToggle: { classPropertyName: "showSidebarToggle", publicName: "showSidebarToggle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { menuItemClick: "menuItemClick", userProfileClick: "userProfileClick", sidebarToggle: "sidebarToggle" }, host: { attributes: { "role": "banner" }, properties: { "class.fui-toolbar--fixed": "fixed()" }, classAttribute: "fui-toolbar" }, ngImport: i0, template: "<!-- Sidebar Toggle Button (optional) -->\r\n@if (showSidebarToggle()) {\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__menu-button --sidebar-toggle\"\r\n [attr.aria-label]=\"'Toggle sidebar'\"\r\n title=\"Toggle sidebar\"\r\n (click)=\"onSidebarToggleClick()\"\r\n >\r\n <fui-icon name=\"sidebar\" size=\"md\"></fui-icon>\r\n </button>\r\n}\r\n<!-- Logo Section -->\r\n<div class=\"fui-toolbar__logo\">\r\n <ng-content select=\"[logo]\"></ng-content>\r\n</div>\r\n\r\n<!-- Navigation Menu -->\r\n<nav class=\"fui-toolbar__nav\" role=\"navigation\" [attr.aria-label]=\"ariaLabel()\">\r\n <ul class=\"fui-toolbar__menu\">\r\n @for (item of menuItems(); track item.id) {\r\n <li class=\"fui-toolbar__menu-item\">\r\n @if (item.routerLink) {\r\n <a\r\n class=\"fui-toolbar__menu-button\"\r\n [class.active]=\"item.id === activeMenuItemId()\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [fragment]=\"item.fragment\"\r\n [attr.aria-current]=\"item.id === activeMenuItemId() ? 'page' : null\"\r\n [attr.aria-label]=\"item.label\"\r\n [title]=\"item.label\"\r\n >\r\n <fui-icon [name]=\"item.icon\" size=\"md\"></fui-icon>\r\n </a>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__menu-button\"\r\n [class.active]=\"item.id === activeMenuItemId()\"\r\n [class.fui-toolbar__menu-button--disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-label]=\"item.label\"\r\n [attr.aria-pressed]=\"item.id === activeMenuItemId() ? 'true' : null\"\r\n [title]=\"item.label\"\r\n (click)=\"onMenuItemClick(item)\"\r\n >\r\n <fui-icon [name]=\"item.icon\" size=\"md\"></fui-icon>\r\n </button>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</nav>\r\n<div class=\"fui-toolbar__spacer\"></div>\r\n<div class=\"fui-toolbar__more-buttons\">\r\n <ng-content select=\"[more-buttons]\"></ng-content>\r\n</div>\r\n<!-- User Profile Section -->\r\n@if (userProfile(); as profile) {\r\n <div class=\"fui-toolbar__user\">\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__user-button\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-label]=\"userAriaLabel() + profile.name\"\r\n [title]=\"profile.name + ' - ' + profile.email\"\r\n (click)=\"onUserProfileClick()\"\r\n >\r\n <fui-avatar [size]=\"32\" [name]=\"firstName()\" [surname]=\"lastName()\" [avatarUrl]=\"profile.avatar ?? null\">\r\n </fui-avatar>\r\n\r\n <div class=\"fui-toolbar__user-info\">\r\n <span class=\"fui-toolbar__user-name\">{{ profile.name }}</span>\r\n <span class=\"fui-toolbar__user-email\">{{ profile.email }}</span>\r\n </div>\r\n\r\n <fui-icon name=\"caret-down\" size=\"sm\" class=\"fui-toolbar__user-caret\"></fui-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [".fui-toolbar{--fui-toolbar-height: 3rem;--fui-toolbar-padding-inline: var(--fui-spacing-05);--fui-toolbar-bg: var(--fui-surface-02);--fui-toolbar-border-color: var(--fui-border-color);--fui-toolbar-blur: 8px;--fui-toolbar-item-size: 3rem;--fui-toolbar-logo-image-max-height: 2rem;--fui-toolbar-user-text-max-width: 8rem;contain:layout style;display:flex;align-items:center;justify-content:space-between;width:100%;height:var(--fui-toolbar-height);padding-block:0;padding-inline:var(--fui-toolbar-padding-inline);background-color:var(--fui-toolbar-bg) CC;-webkit-backdrop-filter:blur(var(--fui-toolbar-blur));backdrop-filter:blur(var(--fui-toolbar-blur));border-bottom:1px solid var(--fui-toolbar-border-color);z-index:var(--fui-z-sticky, 1000)}.fui-toolbar--fixed{position:fixed;top:0;left:0;right:0}.fui-toolbar__logo{display:flex;align-items:center;flex-shrink:0;height:100%;min-width:0;margin-right:.75rem}.fui-toolbar__logo [logo]{display:flex;align-items:center;height:100%}.fui-toolbar__logo [logo] img{max-height:var(--fui-toolbar-logo-image-max-height, 2rem);width:auto}.fui-toolbar__logo [logo] h1,.fui-toolbar__logo [logo] h2,.fui-toolbar__logo [logo] h3{margin:0;font-size:var(--fui-font-size-04);font-weight:600;color:var(--fui-text-primary)}.fui-toolbar__spacer{flex:1;min-width:0}.fui-toolbar__more-buttons{border-left:1px solid var(--fui-border-color);padding:0 .25rem;height:100%;display:flex;align-items:center;gap:.25rem;flex-shrink:0;min-width:0}.fui-toolbar__more-buttons:empty{display:none}.fui-toolbar__nav{flex:1;display:flex;justify-content:flex-start;max-width:100%;overflow:hidden}.fui-toolbar__menu{display:flex;align-items:center;gap:.25rem;list-style:none;margin:0;padding:0}.fui-toolbar__menu-item{display:flex}.fui-toolbar__menu-button{display:flex;align-items:center;justify-content:center;width:var(--fui-toolbar-item-size, 3rem);height:var(--fui-toolbar-item-size, 3rem);padding:0;border:none;border-radius:var(--fui-border-radius-lg, 6px);background-color:transparent;color:var(--fui-icon-primary);cursor:pointer;transition:all var(--fui-duration-fast-02, .12s) var(--fui-ease-standard, ease)}.fui-toolbar__menu-button.--sidebar-toggle{margin-right:.75rem}.fui-toolbar__menu-button:hover:not(:disabled){background-color:var(--fui-surface-02);color:var(--fui-primary-hover)}.fui-toolbar__menu-button:active:not(:disabled),.fui-toolbar__menu-button.active:not(:disabled){background-color:var(--fui-surface-05);color:var(--fui-primary)}.fui-toolbar__menu-button:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-toolbar__menu-button--disabled{color:var(--fui-icon-on-color-disabled);cursor:not-allowed}.fui-toolbar__user{border-left:1px solid var(--fui-border-color);display:flex;align-items:center;flex-shrink:0;margin-right:-1rem}.fui-toolbar__user-button{display:flex;align-items:center;gap:.5rem;padding:.25rem .75rem;border:none;border-radius:var(--fui-border-radius-md, 6px);background-color:transparent;color:var(--fui-text-primary);cursor:pointer;transition:all var(--fui-duration-fast-02, .12s) var(--fui-ease-standard, ease);min-width:0}.fui-toolbar__user-button:hover{background-color:var(--fui-surface-02)}.fui-toolbar__user-button:active{background-color:var(--fui-surface-05)}.fui-toolbar__user-button:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-toolbar__user-info{display:flex;flex-direction:column;align-items:flex-start;min-width:0;flex:1}@media(max-width:768px){.fui-toolbar__user-info{display:none}}.fui-toolbar__user-name{font-size:var(--fui-font-size-02);font-weight:500;color:var(--fui-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:var(--fui-toolbar-user-text-max-width, 8rem)}.fui-toolbar__user-email{font-size:var(--fui-font-size-01);color:var(--fui-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:8rem}.fui-toolbar__user-caret{flex-shrink:0;color:var(--fui-icon-secondary);transition:transform var(--fui-duration-fast-02, .12s) var(--fui-ease-standard, ease)}@media(max-width:576px){.fui-toolbar__user-caret{display:none}}@media(max-width:768px){.fui-toolbar{padding:0 .75rem}.fui-toolbar__menu{gap:.125rem}.fui-toolbar__menu-button{width:var(--fui-toolbar-item-size-md, 2.25rem);height:var(--fui-toolbar-item-size-md, 2.25rem)}}@media(max-width:576px){.fui-toolbar{padding:0 .5rem}.fui-toolbar__nav{flex:0;margin:0 .5rem}.fui-toolbar__menu{gap:0}.fui-toolbar__menu-button{width:var(--fui-toolbar-item-size-sm, 2rem);height:var(--fui-toolbar-item-size-sm, 2rem)}.fui-toolbar__user-button{padding:.25rem;gap:.25rem}}.fui-theme-dark .fui-toolbar{border-bottom-color:var(--fui-border-color)}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }, { kind: "component", type: FuiAvatarComponent, selector: "fui-avatar", inputs: ["size", "shape", "src", "avatarUrl", "srcSet", "sizesAttr", "name", "surname", "fullName", "alt", "identityKey"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
125
|
+
}
|
|
126
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiToolbarComponent, decorators: [{
|
|
127
|
+
type: Component,
|
|
128
|
+
args: [{ selector: 'fui-toolbar', standalone: true, imports: [RouterModule, FuiIconComponent, FuiAvatarComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
129
|
+
class: 'fui-toolbar',
|
|
130
|
+
role: 'banner',
|
|
131
|
+
'[class.fui-toolbar--fixed]': 'fixed()',
|
|
132
|
+
}, template: "<!-- Sidebar Toggle Button (optional) -->\r\n@if (showSidebarToggle()) {\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__menu-button --sidebar-toggle\"\r\n [attr.aria-label]=\"'Toggle sidebar'\"\r\n title=\"Toggle sidebar\"\r\n (click)=\"onSidebarToggleClick()\"\r\n >\r\n <fui-icon name=\"sidebar\" size=\"md\"></fui-icon>\r\n </button>\r\n}\r\n<!-- Logo Section -->\r\n<div class=\"fui-toolbar__logo\">\r\n <ng-content select=\"[logo]\"></ng-content>\r\n</div>\r\n\r\n<!-- Navigation Menu -->\r\n<nav class=\"fui-toolbar__nav\" role=\"navigation\" [attr.aria-label]=\"ariaLabel()\">\r\n <ul class=\"fui-toolbar__menu\">\r\n @for (item of menuItems(); track item.id) {\r\n <li class=\"fui-toolbar__menu-item\">\r\n @if (item.routerLink) {\r\n <a\r\n class=\"fui-toolbar__menu-button\"\r\n [class.active]=\"item.id === activeMenuItemId()\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [fragment]=\"item.fragment\"\r\n [attr.aria-current]=\"item.id === activeMenuItemId() ? 'page' : null\"\r\n [attr.aria-label]=\"item.label\"\r\n [title]=\"item.label\"\r\n >\r\n <fui-icon [name]=\"item.icon\" size=\"md\"></fui-icon>\r\n </a>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__menu-button\"\r\n [class.active]=\"item.id === activeMenuItemId()\"\r\n [class.fui-toolbar__menu-button--disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-label]=\"item.label\"\r\n [attr.aria-pressed]=\"item.id === activeMenuItemId() ? 'true' : null\"\r\n [title]=\"item.label\"\r\n (click)=\"onMenuItemClick(item)\"\r\n >\r\n <fui-icon [name]=\"item.icon\" size=\"md\"></fui-icon>\r\n </button>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</nav>\r\n<div class=\"fui-toolbar__spacer\"></div>\r\n<div class=\"fui-toolbar__more-buttons\">\r\n <ng-content select=\"[more-buttons]\"></ng-content>\r\n</div>\r\n<!-- User Profile Section -->\r\n@if (userProfile(); as profile) {\r\n <div class=\"fui-toolbar__user\">\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__user-button\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-label]=\"userAriaLabel() + profile.name\"\r\n [title]=\"profile.name + ' - ' + profile.email\"\r\n (click)=\"onUserProfileClick()\"\r\n >\r\n <fui-avatar [size]=\"32\" [name]=\"firstName()\" [surname]=\"lastName()\" [avatarUrl]=\"profile.avatar ?? null\">\r\n </fui-avatar>\r\n\r\n <div class=\"fui-toolbar__user-info\">\r\n <span class=\"fui-toolbar__user-name\">{{ profile.name }}</span>\r\n <span class=\"fui-toolbar__user-email\">{{ profile.email }}</span>\r\n </div>\r\n\r\n <fui-icon name=\"caret-down\" size=\"sm\" class=\"fui-toolbar__user-caret\"></fui-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [".fui-toolbar{--fui-toolbar-height: 3rem;--fui-toolbar-padding-inline: var(--fui-spacing-05);--fui-toolbar-bg: var(--fui-surface-02);--fui-toolbar-border-color: var(--fui-border-color);--fui-toolbar-blur: 8px;--fui-toolbar-item-size: 3rem;--fui-toolbar-logo-image-max-height: 2rem;--fui-toolbar-user-text-max-width: 8rem;contain:layout style;display:flex;align-items:center;justify-content:space-between;width:100%;height:var(--fui-toolbar-height);padding-block:0;padding-inline:var(--fui-toolbar-padding-inline);background-color:var(--fui-toolbar-bg) CC;-webkit-backdrop-filter:blur(var(--fui-toolbar-blur));backdrop-filter:blur(var(--fui-toolbar-blur));border-bottom:1px solid var(--fui-toolbar-border-color);z-index:var(--fui-z-sticky, 1000)}.fui-toolbar--fixed{position:fixed;top:0;left:0;right:0}.fui-toolbar__logo{display:flex;align-items:center;flex-shrink:0;height:100%;min-width:0;margin-right:.75rem}.fui-toolbar__logo [logo]{display:flex;align-items:center;height:100%}.fui-toolbar__logo [logo] img{max-height:var(--fui-toolbar-logo-image-max-height, 2rem);width:auto}.fui-toolbar__logo [logo] h1,.fui-toolbar__logo [logo] h2,.fui-toolbar__logo [logo] h3{margin:0;font-size:var(--fui-font-size-04);font-weight:600;color:var(--fui-text-primary)}.fui-toolbar__spacer{flex:1;min-width:0}.fui-toolbar__more-buttons{border-left:1px solid var(--fui-border-color);padding:0 .25rem;height:100%;display:flex;align-items:center;gap:.25rem;flex-shrink:0;min-width:0}.fui-toolbar__more-buttons:empty{display:none}.fui-toolbar__nav{flex:1;display:flex;justify-content:flex-start;max-width:100%;overflow:hidden}.fui-toolbar__menu{display:flex;align-items:center;gap:.25rem;list-style:none;margin:0;padding:0}.fui-toolbar__menu-item{display:flex}.fui-toolbar__menu-button{display:flex;align-items:center;justify-content:center;width:var(--fui-toolbar-item-size, 3rem);height:var(--fui-toolbar-item-size, 3rem);padding:0;border:none;border-radius:var(--fui-border-radius-lg, 6px);background-color:transparent;color:var(--fui-icon-primary);cursor:pointer;transition:all var(--fui-duration-fast-02, .12s) var(--fui-ease-standard, ease)}.fui-toolbar__menu-button.--sidebar-toggle{margin-right:.75rem}.fui-toolbar__menu-button:hover:not(:disabled){background-color:var(--fui-surface-02);color:var(--fui-primary-hover)}.fui-toolbar__menu-button:active:not(:disabled),.fui-toolbar__menu-button.active:not(:disabled){background-color:var(--fui-surface-05);color:var(--fui-primary)}.fui-toolbar__menu-button:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-toolbar__menu-button--disabled{color:var(--fui-icon-on-color-disabled);cursor:not-allowed}.fui-toolbar__user{border-left:1px solid var(--fui-border-color);display:flex;align-items:center;flex-shrink:0;margin-right:-1rem}.fui-toolbar__user-button{display:flex;align-items:center;gap:.5rem;padding:.25rem .75rem;border:none;border-radius:var(--fui-border-radius-md, 6px);background-color:transparent;color:var(--fui-text-primary);cursor:pointer;transition:all var(--fui-duration-fast-02, .12s) var(--fui-ease-standard, ease);min-width:0}.fui-toolbar__user-button:hover{background-color:var(--fui-surface-02)}.fui-toolbar__user-button:active{background-color:var(--fui-surface-05)}.fui-toolbar__user-button:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-toolbar__user-info{display:flex;flex-direction:column;align-items:flex-start;min-width:0;flex:1}@media(max-width:768px){.fui-toolbar__user-info{display:none}}.fui-toolbar__user-name{font-size:var(--fui-font-size-02);font-weight:500;color:var(--fui-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:var(--fui-toolbar-user-text-max-width, 8rem)}.fui-toolbar__user-email{font-size:var(--fui-font-size-01);color:var(--fui-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:8rem}.fui-toolbar__user-caret{flex-shrink:0;color:var(--fui-icon-secondary);transition:transform var(--fui-duration-fast-02, .12s) var(--fui-ease-standard, ease)}@media(max-width:576px){.fui-toolbar__user-caret{display:none}}@media(max-width:768px){.fui-toolbar{padding:0 .75rem}.fui-toolbar__menu{gap:.125rem}.fui-toolbar__menu-button{width:var(--fui-toolbar-item-size-md, 2.25rem);height:var(--fui-toolbar-item-size-md, 2.25rem)}}@media(max-width:576px){.fui-toolbar{padding:0 .5rem}.fui-toolbar__nav{flex:0;margin:0 .5rem}.fui-toolbar__menu{gap:0}.fui-toolbar__menu-button{width:var(--fui-toolbar-item-size-sm, 2rem);height:var(--fui-toolbar-item-size-sm, 2rem)}.fui-toolbar__user-button{padding:.25rem;gap:.25rem}}.fui-theme-dark .fui-toolbar{border-bottom-color:var(--fui-border-color)}\n"] }]
|
|
133
|
+
}], propDecorators: { menuItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuItems", required: false }] }], userProfile: [{ type: i0.Input, args: [{ isSignal: true, alias: "userProfile", required: false }] }], fixed: [{ type: i0.Input, args: [{ isSignal: true, alias: "fixed", required: false }] }], activeMenuItemId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeMenuItemId", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], userAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "userAriaLabel", required: false }] }], showSidebarToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSidebarToggle", required: false }] }], menuItemClick: [{ type: i0.Output, args: ["menuItemClick"] }], userProfileClick: [{ type: i0.Output, args: ["userProfileClick"] }], sidebarToggle: [{ type: i0.Output, args: ["sidebarToggle"] }] } });
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Generated bundle index. Do not edit.
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
export { FuiToolbarComponent };
|
|
140
|
+
//# sourceMappingURL=raintonic-formaui-components-toolbar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raintonic-formaui-components-toolbar.mjs","sources":["../../../lib/components/toolbar/toolbar.component.ts","../../../lib/components/toolbar/toolbar.component.html","../../../lib/components/toolbar/raintonic-formaui-components-toolbar.ts"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n input,\n output,\n computed,\n InputSignal,\n OutputEmitterRef,\n Signal,\n} from '@angular/core';\n\nimport { RouterModule } from '@angular/router';\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\nimport { FuiAvatarComponent } from '@raintonic/formaui/components/avatar';\n\n/**\n * Toolbar menu item interface\n */\nexport interface FuiToolbarMenuItem {\n id: string | number;\n icon: string;\n label: string;\n disabled?: boolean;\n routerLink?: string | string[];\n queryParams?: Record<string, string>;\n fragment?: string;\n}\n\n/**\n * User profile data interface\n */\nexport interface FuiToolbarUserProfile {\n name: string;\n email: string;\n avatar?: string;\n initials?: string;\n}\n\n/**\n * # FuiToolbar Component\n *\n * A top navigation toolbar following Carbon Design System principles.\n * Provides space for logo, navigation menu items, and user profile area.\n *\n * ## Features\n * - Logo area with customizable content\n * - Icon-based navigation menu\n * - User profile area with avatar/initials\n * - Responsive design\n * - Theme integration\n * - Accessibility support\n *\n * ## Usage\n *\n * ### Basic Toolbar\n * ```html\n * <fui-toolbar\n * [menuItems]=\"menuItems\"\n * [userProfile]=\"userProfile\"\n * (menuItemClick)=\"onMenuItemClick($event)\"\n * (userProfileClick)=\"onUserProfileClick()\">\n * <div logo>\n * <img src=\"logo.svg\" alt=\"Company Logo\">\n * </div>\n * </fui-toolbar>\n * ```\n *\n * ### With Custom Logo\n * ```html\n * <fui-toolbar [menuItems]=\"menuItems\" [userProfile]=\"userProfile\">\n * <div logo class=\"custom-logo\">\n * <h1>Holiday ERP</h1>\n * </div>\n * </fui-toolbar>\n * ```\n *\n * @example\n * ```typescript\n * import { FuiToolbarComponent, FuiToolbarMenuItem, FuiToolbarUserProfile } from '@raintonic/formaui/components/toolbar';\n *\n * @Component({\n * standalone: true,\n * imports: [FuiToolbarComponent],\n * template: `\n * <fui-toolbar\n * [menuItems]=\"menuItems\"\n * [userProfile]=\"userProfile\"\n * (menuItemClick)=\"onMenuItemClick($event)\"\n * (userProfileClick)=\"onUserProfileClick()\">\n * <div logo>\n * <img src=\"assets/logo.svg\" alt=\"Holiday ERP\">\n * </div>\n * </fui-toolbar>\n * `\n * })\n * export class AppLayoutComponent {\n * menuItems: FuiToolbarMenuItem[] = [\n * { id: 'dashboard', icon: 'house', label: 'Dashboard' },\n * { id: 'orders', icon: 'shopping-cart', label: 'Orders' },\n * { id: 'products', icon: 'package', label: 'Products' },\n * { id: 'customers', icon: 'users', label: 'Customers' },\n * ];\n *\n * userProfile: FuiToolbarUserProfile = {\n * name: 'John Doe',\n * email: 'john.doe@company.com',\n * initials: 'JD'\n * };\n *\n * onMenuItemClick(itemId: string | number): void {\n * console.log('Menu item clicked:', itemId);\n * }\n *\n * onUserProfileClick(): void {\n * console.log('User profile clicked');\n * }\n * }\n * ```\n */\n@Component({\n selector: 'fui-toolbar',\n standalone: true,\n imports: [RouterModule, FuiIconComponent, FuiAvatarComponent],\n templateUrl: './toolbar.component.html',\n styleUrls: ['./toolbar.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-toolbar',\n role: 'banner',\n '[class.fui-toolbar--fixed]': 'fixed()',\n },\n})\nexport class FuiToolbarComponent {\n // Inputs using signal-based API\n readonly menuItems: InputSignal<FuiToolbarMenuItem[]> = input<FuiToolbarMenuItem[]>([]);\n readonly userProfile: InputSignal<FuiToolbarUserProfile | null> = input<FuiToolbarUserProfile | null>(null);\n readonly fixed: InputSignal<boolean> = input(true);\n readonly activeMenuItemId: InputSignal<string | number> = input<string | number>('');\n readonly ariaLabel = input('Main navigation');\n readonly userAriaLabel = input('User menu for ');\n // New: show a dedicated sidebar toggle button\n readonly showSidebarToggle: InputSignal<boolean> = input(false);\n\n // Outputs using signal-based API\n readonly menuItemClick: OutputEmitterRef<string | number> = output<string | number>();\n readonly userProfileClick: OutputEmitterRef<void> = output();\n // New: emits when sidebar toggle button is clicked\n readonly sidebarToggle: OutputEmitterRef<void> = output();\n\n // Derived user name parts for avatar\n readonly firstName: Signal<string> = computed(() => this.userProfile()?.name?.trim().split(/\\s+/)[0] ?? '');\n readonly lastName: Signal<string> = computed(() => {\n const parts = this.userProfile()?.name?.trim().split(/\\s+/) ?? [];\n return parts.length > 1 ? parts[parts.length - 1] : '';\n });\n\n onMenuItemClick(item: FuiToolbarMenuItem): void {\n if (!item.disabled) {\n this.menuItemClick.emit(item.id);\n }\n }\n\n onUserProfileClick(): void {\n if (this.userProfile()) {\n this.userProfileClick.emit();\n }\n }\n\n onSidebarToggleClick(): void {\n this.sidebarToggle.emit();\n }\n}\n","<!-- Sidebar Toggle Button (optional) -->\r\n@if (showSidebarToggle()) {\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__menu-button --sidebar-toggle\"\r\n [attr.aria-label]=\"'Toggle sidebar'\"\r\n title=\"Toggle sidebar\"\r\n (click)=\"onSidebarToggleClick()\"\r\n >\r\n <fui-icon name=\"sidebar\" size=\"md\"></fui-icon>\r\n </button>\r\n}\r\n<!-- Logo Section -->\r\n<div class=\"fui-toolbar__logo\">\r\n <ng-content select=\"[logo]\"></ng-content>\r\n</div>\r\n\r\n<!-- Navigation Menu -->\r\n<nav class=\"fui-toolbar__nav\" role=\"navigation\" [attr.aria-label]=\"ariaLabel()\">\r\n <ul class=\"fui-toolbar__menu\">\r\n @for (item of menuItems(); track item.id) {\r\n <li class=\"fui-toolbar__menu-item\">\r\n @if (item.routerLink) {\r\n <a\r\n class=\"fui-toolbar__menu-button\"\r\n [class.active]=\"item.id === activeMenuItemId()\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [fragment]=\"item.fragment\"\r\n [attr.aria-current]=\"item.id === activeMenuItemId() ? 'page' : null\"\r\n [attr.aria-label]=\"item.label\"\r\n [title]=\"item.label\"\r\n >\r\n <fui-icon [name]=\"item.icon\" size=\"md\"></fui-icon>\r\n </a>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__menu-button\"\r\n [class.active]=\"item.id === activeMenuItemId()\"\r\n [class.fui-toolbar__menu-button--disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-label]=\"item.label\"\r\n [attr.aria-pressed]=\"item.id === activeMenuItemId() ? 'true' : null\"\r\n [title]=\"item.label\"\r\n (click)=\"onMenuItemClick(item)\"\r\n >\r\n <fui-icon [name]=\"item.icon\" size=\"md\"></fui-icon>\r\n </button>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</nav>\r\n<div class=\"fui-toolbar__spacer\"></div>\r\n<div class=\"fui-toolbar__more-buttons\">\r\n <ng-content select=\"[more-buttons]\"></ng-content>\r\n</div>\r\n<!-- User Profile Section -->\r\n@if (userProfile(); as profile) {\r\n <div class=\"fui-toolbar__user\">\r\n <button\r\n type=\"button\"\r\n class=\"fui-toolbar__user-button\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-label]=\"userAriaLabel() + profile.name\"\r\n [title]=\"profile.name + ' - ' + profile.email\"\r\n (click)=\"onUserProfileClick()\"\r\n >\r\n <fui-avatar [size]=\"32\" [name]=\"firstName()\" [surname]=\"lastName()\" [avatarUrl]=\"profile.avatar ?? null\">\r\n </fui-avatar>\r\n\r\n <div class=\"fui-toolbar__user-info\">\r\n <span class=\"fui-toolbar__user-name\">{{ profile.name }}</span>\r\n <span class=\"fui-toolbar__user-email\">{{ profile.email }}</span>\r\n </div>\r\n\r\n <fui-icon name=\"caret-down\" size=\"sm\" class=\"fui-toolbar__user-caret\"></fui-icon>\r\n </button>\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|