@ojiepermana/angular 0.0.3 → 0.1.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.
Files changed (31) hide show
  1. package/README.md +50 -7
  2. package/fesm2022/ojiepermana-angular-internal.mjs +417 -2
  3. package/fesm2022/ojiepermana-angular-internal.mjs.map +1 -1
  4. package/fesm2022/ojiepermana-angular-layout.mjs +8 -18
  5. package/fesm2022/ojiepermana-angular-layout.mjs.map +1 -1
  6. package/fesm2022/ojiepermana-angular-navigation-horizontal.mjs +785 -0
  7. package/fesm2022/ojiepermana-angular-navigation-horizontal.mjs.map +1 -0
  8. package/fesm2022/ojiepermana-angular-navigation-vertical.mjs +1568 -0
  9. package/fesm2022/ojiepermana-angular-navigation-vertical.mjs.map +1 -0
  10. package/fesm2022/ojiepermana-angular-navigation.mjs +176 -0
  11. package/fesm2022/ojiepermana-angular-navigation.mjs.map +1 -0
  12. package/fesm2022/ojiepermana-angular-theme-component.mjs +12 -26
  13. package/fesm2022/ojiepermana-angular-theme-component.mjs.map +1 -1
  14. package/fesm2022/ojiepermana-angular-theme-service.mjs +2 -6
  15. package/fesm2022/ojiepermana-angular-theme-service.mjs.map +1 -1
  16. package/fesm2022/ojiepermana-angular.mjs.map +1 -1
  17. package/navigation/README.md +215 -0
  18. package/package.json +13 -1
  19. package/theme/README.md +1 -4
  20. package/theme/styles/adapters/material-ui/index.css +1 -5
  21. package/theme/styles/layout/horizontal.css +2 -10
  22. package/theme/styles/layout/vertical.css +3 -5
  23. package/theme/styles/presets/styles/flat.css +3 -6
  24. package/theme/styles/presets/styles/glass.css +1 -7
  25. package/theme/styles/presets/styles/index.css +1 -1
  26. package/theme/styles/roles/index.css +18 -0
  27. package/theme/styles/tokens/foundation.css +4 -7
  28. package/types/ojiepermana-angular-internal.d.ts +64 -1
  29. package/types/ojiepermana-angular-navigation-horizontal.d.ts +77 -0
  30. package/types/ojiepermana-angular-navigation-vertical.d.ts +260 -0
  31. package/types/ojiepermana-angular-navigation.d.ts +182 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ojiepermana-angular-theme-service.mjs","sources":["../../../projects/library/theme/service/src/theme.token.ts","../../../projects/library/theme/service/src/theme.types.ts","../../../projects/library/theme/service/src/theme.service.ts","../../../projects/library/theme/service/src/theme.provider.ts","../../../projects/library/theme/service/ojiepermana-angular-theme-service.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { NgThemeConfig } from './theme.types';\n\nexport const DEFAULT_NG_THEME_CONFIG: NgThemeConfig = {\n defaultScheme: 'system',\n defaultColor: 'brand',\n defaultStyle: 'flat',\n};\n\nexport const NG_THEME_CONFIG = new InjectionToken<NgThemeConfig>('NG_THEME_CONFIG', {\n providedIn: 'root',\n factory: () => ({ ...DEFAULT_NG_THEME_CONFIG }),\n});\n","export const THEME_SCHEMES = ['light', 'dark', 'system'] as const;\nexport type ThemeScheme = (typeof THEME_SCHEMES)[number];\n\nexport const THEME_COLORS = ['brand', 'blue', 'green', 'red', 'cyan', 'purple', 'orange'] as const;\nexport type ThemeColor = (typeof THEME_COLORS)[number];\n\nexport const THEME_STYLES = ['flat', 'glass'] as const;\nexport type ThemeStyle = (typeof THEME_STYLES)[number];\n\nconst THEME_SCHEME_SET = new Set<ThemeScheme>(THEME_SCHEMES);\nconst THEME_COLOR_SET = new Set<ThemeColor>(THEME_COLORS);\nconst THEME_STYLE_SET = new Set<ThemeStyle>(THEME_STYLES);\n\nexport function isThemeScheme(value: unknown): value is ThemeScheme {\n return typeof value === 'string' && THEME_SCHEME_SET.has(value as ThemeScheme);\n}\n\nexport function isThemeColor(value: unknown): value is ThemeColor {\n return typeof value === 'string' && THEME_COLOR_SET.has(value as ThemeColor);\n}\n\nexport function isThemeStyle(value: unknown): value is ThemeStyle {\n return typeof value === 'string' && THEME_STYLE_SET.has(value as ThemeStyle);\n}\n\nexport interface ThemeColorOption {\n readonly value: ThemeColor;\n readonly label: string;\n}\n\nexport type ThemeColorLabels = Partial<Record<ThemeColor, string>>;\n\nexport interface NgThemeConfig {\n defaultScheme: ThemeScheme;\n defaultColor: ThemeColor;\n defaultStyle: ThemeStyle;\n colors?: readonly ThemeColor[];\n colorLabels?: ThemeColorLabels;\n}\n","import {\n DestroyRef,\n Injectable,\n PLATFORM_ID,\n computed,\n effect,\n inject,\n signal,\n} from '@angular/core';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { LocalStorageStateAdapter } from '@ojiepermana/angular/internal';\nimport { NG_THEME_CONFIG } from './theme.token';\nimport {\n isThemeColor,\n isThemeScheme,\n isThemeStyle,\n NgThemeConfig,\n ThemeStyle,\n ThemeColor,\n ThemeColorLabels,\n ThemeColorOption,\n ThemeScheme,\n} from './theme.types';\n\nconst THEME_COLOR_OPTIONS: readonly ThemeColorOption[] = [\n { value: 'brand', label: 'Brand' },\n { value: 'blue', label: 'Blue' },\n { value: 'green', label: 'Green' },\n { value: 'red', label: 'Red' },\n { value: 'cyan', label: 'Cyan' },\n { value: 'purple', label: 'Purple' },\n { value: 'orange', label: 'Orange' },\n] as const;\n\nfunction createThemeColorOptions(\n allowedColors: readonly ThemeColor[] | undefined,\n colorLabels: ThemeColorLabels | undefined,\n): readonly ThemeColorOption[] {\n const allowedSet = allowedColors ? new Set(allowedColors) : null;\n\n return THEME_COLOR_OPTIONS.filter((option) => !allowedSet || allowedSet.has(option.value)).map(\n (option) => ({\n value: option.value,\n label: colorLabels?.[option.value] ?? option.label,\n }),\n );\n}\n\nconst STORAGE_KEYS = {\n scheme: 'theme-scheme',\n color: 'theme-color',\n style: 'theme-style',\n} as const;\n\ntype ThemeStorageAxis = keyof typeof STORAGE_KEYS;\n\nconst LEGACY_STORAGE_PREFIX = 'ng-theme:v2';\n\n@Injectable({ providedIn: 'root' })\nexport class ThemeService {\n private readonly config = inject(NG_THEME_CONFIG);\n private readonly document = inject(DOCUMENT);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly storage = new LocalStorageStateAdapter<ThemeStorageAxis>({\n isBrowser: this.isBrowser,\n storage: this.document.defaultView?.localStorage ?? null,\n keys: STORAGE_KEYS,\n legacyPrefix: LEGACY_STORAGE_PREFIX,\n });\n private readonly mediaQuery = this.isBrowser\n ? typeof this.document.defaultView?.matchMedia === 'function'\n ? this.document.defaultView.matchMedia('(prefers-color-scheme: dark)')\n : null\n : null;\n private readonly systemPrefersDark = signal(this.mediaQuery?.matches ?? false);\n private readonly availableColorOptions = createThemeColorOptions(\n this.config.colors,\n this.config.colorLabels,\n );\n\n readonly scheme = signal<ThemeScheme>(\n this.storage.read('scheme', this.config.defaultScheme, isThemeScheme),\n );\n readonly color = signal<ThemeColor>(\n this.storage.read('color', this.config.defaultColor, isThemeColor),\n );\n readonly style = signal<ThemeStyle>(\n this.storage.read('style', this.config.defaultStyle, isThemeStyle),\n );\n readonly colorOptions = computed<readonly ThemeColorOption[]>(() => this.availableColorOptions);\n\n readonly resolvedScheme = computed<'light' | 'dark'>(() => {\n if (this.scheme() !== 'system') return this.scheme() as 'light' | 'dark';\n return this.systemPrefersDark() ? 'dark' : 'light';\n });\n\n constructor() {\n if (this.mediaQuery) {\n const syncSystemPreference = (event: MediaQueryListEvent): void => {\n this.systemPrefersDark.set(event.matches);\n };\n\n this.mediaQuery.addEventListener('change', syncSystemPreference);\n this.destroyRef.onDestroy(() => {\n this.mediaQuery?.removeEventListener('change', syncSystemPreference);\n });\n }\n\n effect(() => {\n if (this.isBrowser) {\n this.applyToDOM();\n }\n });\n }\n\n /**\n * Updates the selected theme scheme and persists the choice for future sessions.\n */\n setScheme(value: ThemeScheme): void {\n this.storage.persist('scheme', value);\n this.scheme.set(value);\n }\n\n /**\n * Updates the active theme color when it is part of the configured preset list.\n */\n setColor(value: ThemeColor): void {\n if (!this.colorOptions().some((option) => option.value === value)) {\n return;\n }\n\n this.storage.persist('color', value);\n this.color.set(value);\n }\n\n /**\n * Updates the active style preset and persists it to local storage.\n */\n setStyle(value: ThemeStyle): void {\n this.storage.persist('style', value);\n this.style.set(value);\n }\n\n /**\n * Cycles the scheme through light, dark, and system while keeping the DOM contract in sync.\n */\n toggleScheme(): void {\n const next: ThemeScheme =\n this.scheme() === 'light' ? 'dark' : this.scheme() === 'dark' ? 'system' : 'light';\n this.setScheme(next);\n }\n\n /**\n * Clears persisted theme state and restores the configured defaults for all theme axes.\n */\n reset(): void {\n this.storage.clear('scheme');\n this.storage.clear('color');\n this.storage.clear('style');\n this.scheme.set(this.config.defaultScheme);\n this.color.set(this.config.defaultColor);\n this.style.set(this.config.defaultStyle);\n }\n\n private applyToDOM(): void {\n const element = this.document.documentElement;\n\n element.classList.toggle('dark', this.resolvedScheme() === 'dark');\n element.dataset['themeScheme'] = this.scheme();\n element.dataset['themeColor'] = this.color();\n element.dataset['themeStyle'] = this.style();\n element.style.colorScheme = this.resolvedScheme();\n }\n}\n","import { EnvironmentProviders, isDevMode, makeEnvironmentProviders } from '@angular/core';\nimport { DEFAULT_NG_THEME_CONFIG, NG_THEME_CONFIG } from './theme.token';\nimport {\n isThemeColor,\n isThemeScheme,\n isThemeStyle,\n NgThemeConfig,\n ThemeColor,\n ThemeColorLabels,\n ThemeScheme,\n ThemeStyle,\n} from './theme.types';\n\nfunction warnInvalidThemeConfig(message: string): void {\n if (isDevMode()) {\n console.warn(`[provideNgTheme] ${message}`);\n }\n}\n\nfunction normalizeThemeScheme(value: unknown): ThemeScheme {\n if (typeof value === 'undefined' || isThemeScheme(value)) {\n return value ?? DEFAULT_NG_THEME_CONFIG.defaultScheme;\n }\n\n warnInvalidThemeConfig(\n `Ignoring invalid defaultScheme ${JSON.stringify(value)}. Falling back to ${JSON.stringify(DEFAULT_NG_THEME_CONFIG.defaultScheme)}.`,\n );\n\n return DEFAULT_NG_THEME_CONFIG.defaultScheme;\n}\n\nfunction normalizeThemeColor(value: unknown): ThemeColor {\n if (typeof value === 'undefined' || isThemeColor(value)) {\n return value ?? DEFAULT_NG_THEME_CONFIG.defaultColor;\n }\n\n warnInvalidThemeConfig(\n `Ignoring invalid defaultColor ${JSON.stringify(value)}. Falling back to ${JSON.stringify(DEFAULT_NG_THEME_CONFIG.defaultColor)}.`,\n );\n\n return DEFAULT_NG_THEME_CONFIG.defaultColor;\n}\n\nfunction normalizeThemeStyle(value: unknown): ThemeStyle {\n if (typeof value === 'undefined' || isThemeStyle(value)) {\n return value ?? DEFAULT_NG_THEME_CONFIG.defaultStyle;\n }\n\n warnInvalidThemeConfig(\n `Ignoring invalid defaultStyle ${JSON.stringify(value)}. Falling back to ${JSON.stringify(DEFAULT_NG_THEME_CONFIG.defaultStyle)}.`,\n );\n\n return DEFAULT_NG_THEME_CONFIG.defaultStyle;\n}\n\nfunction normalizeThemeColors(value: unknown): readonly ThemeColor[] | undefined {\n if (typeof value === 'undefined') {\n return undefined;\n }\n\n if (!Array.isArray(value)) {\n warnInvalidThemeConfig('Ignoring invalid colors config because it is not an array.');\n return undefined;\n }\n\n const normalizedColors = Array.from(new Set(value.filter(isThemeColor)));\n\n if (normalizedColors.length !== value.length) {\n warnInvalidThemeConfig('Ignoring unsupported values in colors config.');\n }\n\n return normalizedColors.length > 0 ? normalizedColors : undefined;\n}\n\nfunction normalizeThemeColorLabels(value: unknown): ThemeColorLabels | undefined {\n if (typeof value === 'undefined') {\n return undefined;\n }\n\n if (!value || Array.isArray(value) || typeof value !== 'object') {\n warnInvalidThemeConfig('Ignoring invalid colorLabels config because it is not an object map.');\n return undefined;\n }\n\n const entries = Object.entries(value);\n const normalizedEntries = entries.flatMap(([color, label]) => {\n if (isThemeColor(color) && typeof label === 'string' && label.trim().length > 0) {\n return [[color, label.trim()] as const];\n }\n\n return [];\n });\n\n if (normalizedEntries.length !== entries.length) {\n warnInvalidThemeConfig('Ignoring unsupported entries in colorLabels config.');\n }\n\n return normalizedEntries.length > 0\n ? (Object.fromEntries(normalizedEntries) as ThemeColorLabels)\n : undefined;\n}\n\nfunction normalizeThemeConfig(config: Partial<NgThemeConfig>): NgThemeConfig {\n const colors = normalizeThemeColors(config.colors);\n const colorLabels = normalizeThemeColorLabels(config.colorLabels);\n let defaultColor = normalizeThemeColor(config.defaultColor);\n\n if (colors && !colors.includes(defaultColor)) {\n warnInvalidThemeConfig(\n `Adjusting defaultColor ${JSON.stringify(defaultColor)} to ${JSON.stringify(colors[0])} so it stays within the configured colors list.`,\n );\n defaultColor = colors[0];\n }\n\n return {\n ...DEFAULT_NG_THEME_CONFIG,\n defaultScheme: normalizeThemeScheme(config.defaultScheme),\n defaultColor,\n defaultStyle: normalizeThemeStyle(config.defaultStyle),\n ...(colors ? { colors } : {}),\n ...(colorLabels ? { colorLabels } : {}),\n };\n}\n\nexport function provideNgTheme(config: Partial<NgThemeConfig> = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: NG_THEME_CONFIG, useValue: normalizeThemeConfig(config) },\n ]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ojiepermana-angular-theme-service.mjs","sources":["../../../projects/library/theme/service/src/theme.token.ts","../../../projects/library/theme/service/src/theme.types.ts","../../../projects/library/theme/service/src/theme.service.ts","../../../projects/library/theme/service/src/theme.provider.ts","../../../projects/library/theme/service/ojiepermana-angular-theme-service.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { NgThemeConfig } from './theme.types';\n\nexport const DEFAULT_NG_THEME_CONFIG: NgThemeConfig = {\n defaultScheme: 'system',\n defaultColor: 'brand',\n defaultStyle: 'flat',\n};\n\nexport const NG_THEME_CONFIG = new InjectionToken<NgThemeConfig>('NG_THEME_CONFIG', {\n providedIn: 'root',\n factory: () => ({ ...DEFAULT_NG_THEME_CONFIG }),\n});\n","export const THEME_SCHEMES = ['light', 'dark', 'system'] as const;\nexport type ThemeScheme = (typeof THEME_SCHEMES)[number];\n\nexport const THEME_COLORS = ['brand', 'blue', 'green', 'red', 'cyan', 'purple', 'orange'] as const;\nexport type ThemeColor = (typeof THEME_COLORS)[number];\n\nexport const THEME_STYLES = ['flat', 'glass'] as const;\nexport type ThemeStyle = (typeof THEME_STYLES)[number];\n\nconst THEME_SCHEME_SET = new Set<ThemeScheme>(THEME_SCHEMES);\nconst THEME_COLOR_SET = new Set<ThemeColor>(THEME_COLORS);\nconst THEME_STYLE_SET = new Set<ThemeStyle>(THEME_STYLES);\n\nexport function isThemeScheme(value: unknown): value is ThemeScheme {\n return typeof value === 'string' && THEME_SCHEME_SET.has(value as ThemeScheme);\n}\n\nexport function isThemeColor(value: unknown): value is ThemeColor {\n return typeof value === 'string' && THEME_COLOR_SET.has(value as ThemeColor);\n}\n\nexport function isThemeStyle(value: unknown): value is ThemeStyle {\n return typeof value === 'string' && THEME_STYLE_SET.has(value as ThemeStyle);\n}\n\nexport interface ThemeColorOption {\n readonly value: ThemeColor;\n readonly label: string;\n}\n\nexport type ThemeColorLabels = Partial<Record<ThemeColor, string>>;\n\nexport interface NgThemeConfig {\n defaultScheme: ThemeScheme;\n defaultColor: ThemeColor;\n defaultStyle: ThemeStyle;\n colors?: readonly ThemeColor[];\n colorLabels?: ThemeColorLabels;\n}\n","import { DestroyRef, Injectable, PLATFORM_ID, computed, effect, inject, signal } from '@angular/core';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { LocalStorageStateAdapter } from '@ojiepermana/angular/internal';\nimport { NG_THEME_CONFIG } from './theme.token';\nimport {\n isThemeColor,\n isThemeScheme,\n isThemeStyle,\n NgThemeConfig,\n ThemeStyle,\n ThemeColor,\n ThemeColorLabels,\n ThemeColorOption,\n ThemeScheme,\n} from './theme.types';\n\nconst THEME_COLOR_OPTIONS: readonly ThemeColorOption[] = [\n { value: 'brand', label: 'Brand' },\n { value: 'blue', label: 'Blue' },\n { value: 'green', label: 'Green' },\n { value: 'red', label: 'Red' },\n { value: 'cyan', label: 'Cyan' },\n { value: 'purple', label: 'Purple' },\n { value: 'orange', label: 'Orange' },\n] as const;\n\nfunction createThemeColorOptions(\n allowedColors: readonly ThemeColor[] | undefined,\n colorLabels: ThemeColorLabels | undefined,\n): readonly ThemeColorOption[] {\n const allowedSet = allowedColors ? new Set(allowedColors) : null;\n\n return THEME_COLOR_OPTIONS.filter((option) => !allowedSet || allowedSet.has(option.value)).map((option) => ({\n value: option.value,\n label: colorLabels?.[option.value] ?? option.label,\n }));\n}\n\nconst STORAGE_KEYS = {\n scheme: 'theme-scheme',\n color: 'theme-color',\n style: 'theme-style',\n} as const;\n\ntype ThemeStorageAxis = keyof typeof STORAGE_KEYS;\n\nconst LEGACY_STORAGE_PREFIX = 'ng-theme:v2';\n\n@Injectable({ providedIn: 'root' })\nexport class ThemeService {\n private readonly config = inject(NG_THEME_CONFIG);\n private readonly document = inject(DOCUMENT);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly storage = new LocalStorageStateAdapter<ThemeStorageAxis>({\n isBrowser: this.isBrowser,\n storage: this.document.defaultView?.localStorage ?? null,\n keys: STORAGE_KEYS,\n legacyPrefix: LEGACY_STORAGE_PREFIX,\n });\n private readonly mediaQuery = this.isBrowser\n ? typeof this.document.defaultView?.matchMedia === 'function'\n ? this.document.defaultView.matchMedia('(prefers-color-scheme: dark)')\n : null\n : null;\n private readonly systemPrefersDark = signal(this.mediaQuery?.matches ?? false);\n private readonly availableColorOptions = createThemeColorOptions(this.config.colors, this.config.colorLabels);\n\n readonly scheme = signal<ThemeScheme>(this.storage.read('scheme', this.config.defaultScheme, isThemeScheme));\n readonly color = signal<ThemeColor>(this.storage.read('color', this.config.defaultColor, isThemeColor));\n readonly style = signal<ThemeStyle>(this.storage.read('style', this.config.defaultStyle, isThemeStyle));\n readonly colorOptions = computed<readonly ThemeColorOption[]>(() => this.availableColorOptions);\n\n readonly resolvedScheme = computed<'light' | 'dark'>(() => {\n if (this.scheme() !== 'system') return this.scheme() as 'light' | 'dark';\n return this.systemPrefersDark() ? 'dark' : 'light';\n });\n\n constructor() {\n if (this.mediaQuery) {\n const syncSystemPreference = (event: MediaQueryListEvent): void => {\n this.systemPrefersDark.set(event.matches);\n };\n\n this.mediaQuery.addEventListener('change', syncSystemPreference);\n this.destroyRef.onDestroy(() => {\n this.mediaQuery?.removeEventListener('change', syncSystemPreference);\n });\n }\n\n effect(() => {\n if (this.isBrowser) {\n this.applyToDOM();\n }\n });\n }\n\n /**\n * Updates the selected theme scheme and persists the choice for future sessions.\n */\n setScheme(value: ThemeScheme): void {\n this.storage.persist('scheme', value);\n this.scheme.set(value);\n }\n\n /**\n * Updates the active theme color when it is part of the configured preset list.\n */\n setColor(value: ThemeColor): void {\n if (!this.colorOptions().some((option) => option.value === value)) {\n return;\n }\n\n this.storage.persist('color', value);\n this.color.set(value);\n }\n\n /**\n * Updates the active style preset and persists it to local storage.\n */\n setStyle(value: ThemeStyle): void {\n this.storage.persist('style', value);\n this.style.set(value);\n }\n\n /**\n * Cycles the scheme through light, dark, and system while keeping the DOM contract in sync.\n */\n toggleScheme(): void {\n const next: ThemeScheme = this.scheme() === 'light' ? 'dark' : this.scheme() === 'dark' ? 'system' : 'light';\n this.setScheme(next);\n }\n\n /**\n * Clears persisted theme state and restores the configured defaults for all theme axes.\n */\n reset(): void {\n this.storage.clear('scheme');\n this.storage.clear('color');\n this.storage.clear('style');\n this.scheme.set(this.config.defaultScheme);\n this.color.set(this.config.defaultColor);\n this.style.set(this.config.defaultStyle);\n }\n\n private applyToDOM(): void {\n const element = this.document.documentElement;\n\n element.classList.toggle('dark', this.resolvedScheme() === 'dark');\n element.dataset['themeScheme'] = this.scheme();\n element.dataset['themeColor'] = this.color();\n element.dataset['themeStyle'] = this.style();\n element.style.colorScheme = this.resolvedScheme();\n }\n}\n","import { EnvironmentProviders, isDevMode, makeEnvironmentProviders } from '@angular/core';\nimport { DEFAULT_NG_THEME_CONFIG, NG_THEME_CONFIG } from './theme.token';\nimport {\n isThemeColor,\n isThemeScheme,\n isThemeStyle,\n NgThemeConfig,\n ThemeColor,\n ThemeColorLabels,\n ThemeScheme,\n ThemeStyle,\n} from './theme.types';\n\nfunction warnInvalidThemeConfig(message: string): void {\n if (isDevMode()) {\n console.warn(`[provideNgTheme] ${message}`);\n }\n}\n\nfunction normalizeThemeScheme(value: unknown): ThemeScheme {\n if (typeof value === 'undefined' || isThemeScheme(value)) {\n return value ?? DEFAULT_NG_THEME_CONFIG.defaultScheme;\n }\n\n warnInvalidThemeConfig(\n `Ignoring invalid defaultScheme ${JSON.stringify(value)}. Falling back to ${JSON.stringify(DEFAULT_NG_THEME_CONFIG.defaultScheme)}.`,\n );\n\n return DEFAULT_NG_THEME_CONFIG.defaultScheme;\n}\n\nfunction normalizeThemeColor(value: unknown): ThemeColor {\n if (typeof value === 'undefined' || isThemeColor(value)) {\n return value ?? DEFAULT_NG_THEME_CONFIG.defaultColor;\n }\n\n warnInvalidThemeConfig(\n `Ignoring invalid defaultColor ${JSON.stringify(value)}. Falling back to ${JSON.stringify(DEFAULT_NG_THEME_CONFIG.defaultColor)}.`,\n );\n\n return DEFAULT_NG_THEME_CONFIG.defaultColor;\n}\n\nfunction normalizeThemeStyle(value: unknown): ThemeStyle {\n if (typeof value === 'undefined' || isThemeStyle(value)) {\n return value ?? DEFAULT_NG_THEME_CONFIG.defaultStyle;\n }\n\n warnInvalidThemeConfig(\n `Ignoring invalid defaultStyle ${JSON.stringify(value)}. Falling back to ${JSON.stringify(DEFAULT_NG_THEME_CONFIG.defaultStyle)}.`,\n );\n\n return DEFAULT_NG_THEME_CONFIG.defaultStyle;\n}\n\nfunction normalizeThemeColors(value: unknown): readonly ThemeColor[] | undefined {\n if (typeof value === 'undefined') {\n return undefined;\n }\n\n if (!Array.isArray(value)) {\n warnInvalidThemeConfig('Ignoring invalid colors config because it is not an array.');\n return undefined;\n }\n\n const normalizedColors = Array.from(new Set(value.filter(isThemeColor)));\n\n if (normalizedColors.length !== value.length) {\n warnInvalidThemeConfig('Ignoring unsupported values in colors config.');\n }\n\n return normalizedColors.length > 0 ? normalizedColors : undefined;\n}\n\nfunction normalizeThemeColorLabels(value: unknown): ThemeColorLabels | undefined {\n if (typeof value === 'undefined') {\n return undefined;\n }\n\n if (!value || Array.isArray(value) || typeof value !== 'object') {\n warnInvalidThemeConfig('Ignoring invalid colorLabels config because it is not an object map.');\n return undefined;\n }\n\n const entries = Object.entries(value);\n const normalizedEntries = entries.flatMap(([color, label]) => {\n if (isThemeColor(color) && typeof label === 'string' && label.trim().length > 0) {\n return [[color, label.trim()] as const];\n }\n\n return [];\n });\n\n if (normalizedEntries.length !== entries.length) {\n warnInvalidThemeConfig('Ignoring unsupported entries in colorLabels config.');\n }\n\n return normalizedEntries.length > 0 ? (Object.fromEntries(normalizedEntries) as ThemeColorLabels) : undefined;\n}\n\nfunction normalizeThemeConfig(config: Partial<NgThemeConfig>): NgThemeConfig {\n const colors = normalizeThemeColors(config.colors);\n const colorLabels = normalizeThemeColorLabels(config.colorLabels);\n let defaultColor = normalizeThemeColor(config.defaultColor);\n\n if (colors && !colors.includes(defaultColor)) {\n warnInvalidThemeConfig(\n `Adjusting defaultColor ${JSON.stringify(defaultColor)} to ${JSON.stringify(colors[0])} so it stays within the configured colors list.`,\n );\n defaultColor = colors[0];\n }\n\n return {\n ...DEFAULT_NG_THEME_CONFIG,\n defaultScheme: normalizeThemeScheme(config.defaultScheme),\n defaultColor,\n defaultStyle: normalizeThemeStyle(config.defaultStyle),\n ...(colors ? { colors } : {}),\n ...(colorLabels ? { colorLabels } : {}),\n };\n}\n\nexport function provideNgTheme(config: Partial<NgThemeConfig> = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: NG_THEME_CONFIG, useValue: normalizeThemeConfig(config) }]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ojiepermana-angular.mjs","sources":["../../../projects/library/public-api.ts","../../../projects/library/ojiepermana-angular.ts"],"sourcesContent":["/* Public API Surface of @ojiepermana/angular */\n\nexport {};","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAA;;ACAA;;AAEG"}
1
+ {"version":3,"file":"ojiepermana-angular.mjs","sources":["../../../projects/library/public-api.ts","../../../projects/library/ojiepermana-angular.ts"],"sourcesContent":["/* Public API Surface of @ojiepermana/angular */\n\nexport {};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAA;;ACAA;;AAEG"}
@@ -0,0 +1,215 @@
1
+ # Navigation
2
+
3
+ Navigation for `@ojiepermana/angular` is split into three secondary entry points so consumers can import only the state helpers or component variants they need.
4
+
5
+ ## Entry Points
6
+
7
+ - `@ojiepermana/angular/navigation` exposes the navigation item model, utility helpers, and `NavigationService`.
8
+ - `@ojiepermana/angular/navigation/vertical` exposes the vertical navigation container variants and vertical item components.
9
+ - `@ojiepermana/angular/navigation/horizontal` exposes the horizontal navigation container and branch item component.
10
+
11
+ Do not import consumer code from `@ojiepermana/angular/internal` or from source file paths under this folder. Those paths are implementation details and are not part of the public contract.
12
+
13
+ ## Requirements
14
+
15
+ - Configure Angular Router before rendering the navigation components.
16
+ - Import `@ojiepermana/angular/styles/index.css` in the consuming application so the shared theme tokens are available.
17
+ - Use Lucide icon names or aliases in `NavigationItem.icon`. The navigation components resolve icons through `@lucide/angular`.
18
+
19
+ ## Quick Start
20
+
21
+ ### 1. Define a navigation tree
22
+
23
+ ```ts
24
+ import { NavigationItem } from '@ojiepermana/angular/navigation';
25
+
26
+ export const appNavigation = [
27
+ {
28
+ id: 'dashboard',
29
+ title: 'Dashboard',
30
+ type: 'basic',
31
+ icon: 'layout-dashboard',
32
+ link: '/dashboard',
33
+ },
34
+ {
35
+ id: 'workspace',
36
+ title: 'Workspace',
37
+ type: 'collapsable',
38
+ icon: 'folders',
39
+ children: [
40
+ {
41
+ id: 'workspace-overview',
42
+ title: 'Overview',
43
+ type: 'basic',
44
+ link: '/workspace/overview',
45
+ },
46
+ {
47
+ id: 'workspace-settings',
48
+ title: 'Settings',
49
+ type: 'basic',
50
+ link: '/workspace/settings',
51
+ badge: {
52
+ title: 'Beta',
53
+ classes: 'bg-primary text-primary-foreground',
54
+ },
55
+ },
56
+ ],
57
+ },
58
+ ] satisfies NavigationItem[];
59
+ ```
60
+
61
+ ### 2. Render a vertical navigation
62
+
63
+ ```ts
64
+ import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
65
+ import { NavigationItem } from '@ojiepermana/angular/navigation';
66
+ import { VerticalNavigationDefaultComponent } from '@ojiepermana/angular/navigation/vertical';
67
+
68
+ import { appNavigation } from './app.navigation';
69
+
70
+ @Component({
71
+ selector: 'app-shell-navigation',
72
+ imports: [VerticalNavigationDefaultComponent],
73
+ template: `
74
+ <vertical-navigation [navigation]="navigation()" [opened]="true" mode="side" position="left"></vertical-navigation>
75
+ `,
76
+ changeDetection: ChangeDetectionStrategy.OnPush,
77
+ })
78
+ export class ShellNavigationComponent {
79
+ readonly navigation = signal<NavigationItem[]>(appNavigation);
80
+ }
81
+ ```
82
+
83
+ Vertical variants use these selectors:
84
+
85
+ - `<vertical-navigation>` for the default width and density.
86
+ - `<vertical-navigation-compact>` for a narrower layout.
87
+ - `<vertical-navigation-dense>` for a denser layout.
88
+ - `<vertical-navigation-thin>` for the thin icon-first layout.
89
+
90
+ All vertical variants share the same public API surface inherited from the base component, including `navigation`, `opened`, `mode`, `position`, `autoCollapse`, `inner`, `transparentOverlay`, and the `openedChanged` output.
91
+
92
+ ### 3. Render a horizontal navigation
93
+
94
+ ```ts
95
+ import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
96
+ import { NavigationItem } from '@ojiepermana/angular/navigation';
97
+ import { HorizontalNavigation } from '@ojiepermana/angular/navigation/horizontal';
98
+
99
+ import { appNavigation } from './app.navigation';
100
+
101
+ @Component({
102
+ selector: 'app-top-navigation',
103
+ imports: [HorizontalNavigation],
104
+ template: `
105
+ <horizontal-navigation [navigation]="navigation()" (itemClicked)="onItemClicked($event)"></horizontal-navigation>
106
+ `,
107
+ changeDetection: ChangeDetectionStrategy.OnPush,
108
+ })
109
+ export class TopNavigationComponent {
110
+ readonly navigation = signal<NavigationItem[]>(appNavigation);
111
+
112
+ onItemClicked(item: NavigationItem): void {
113
+ console.log('Navigation item clicked:', item.id);
114
+ }
115
+ }
116
+ ```
117
+
118
+ ### 4. Optionally mirror the tree into `NavigationService`
119
+
120
+ `NavigationService` is useful when other parts of the application need lookup helpers, active item state, or expanded item state. Vertical navigation renders from its `navigation` input. Horizontal navigation renders from its `navigation` input first, and falls back to the service only when the input array is empty.
121
+
122
+ ```ts
123
+ import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';
124
+ import { NavigationItem, NavigationService } from '@ojiepermana/angular/navigation';
125
+
126
+ import { appNavigation } from './app.navigation';
127
+
128
+ @Component({
129
+ selector: 'app-navigation-store',
130
+ template: '',
131
+ changeDetection: ChangeDetectionStrategy.OnPush,
132
+ })
133
+ export class NavigationStoreComponent {
134
+ private readonly navigationService = inject(NavigationService);
135
+ readonly navigation = signal<NavigationItem[]>(appNavigation);
136
+
137
+ ngOnInit(): void {
138
+ this.navigationService.storeNavigation(this.navigation());
139
+ }
140
+ }
141
+ ```
142
+
143
+ ## Navigation Item Model
144
+
145
+ Every tree node is a `NavigationItem`. The public union is split across these item types:
146
+
147
+ - `basic` is a leaf item that can route, open an external link, or run an `action` callback.
148
+ - `aside` is a routable branch rendered through the vertical aside panel pattern.
149
+ - `collapsable` is a branch that expands and collapses inline.
150
+ - `group` is a non-routable section label with children.
151
+ - `divider` renders a visual separator.
152
+ - `spacer` renders flexible empty space.
153
+
154
+ Shared fields available on most item types:
155
+
156
+ - `id`, `title`, `subtitle`, `tooltip`, `icon`, `disabled`, and `meta`.
157
+ - `classes.wrapper`, `classes.icon`, `classes.title`, and `classes.subtitle` for per-item styling hooks.
158
+ - `badge.title` and `badge.classes` for optional item badges.
159
+ - `isHidden` for conditional visibility.
160
+
161
+ Routable item fields available on `basic`, `aside`, and `collapsable`:
162
+
163
+ - `link`, `fragment`, `preserveFragment`, `queryParams`, and `queryParamsHandling`.
164
+ - `externalLink` and `target` for external navigation.
165
+ - `exactMatch` and `isActiveMatchOptions` for route activity matching.
166
+ - `action` for click callbacks.
167
+
168
+ ## Navigation Service
169
+
170
+ `NavigationService` is provided in root and exposes navigation state as signals plus a small lookup API.
171
+
172
+ Readonly state:
173
+
174
+ - `navigationItems`
175
+ - `activeItemId`
176
+ - `flatNavigation`
177
+ - `expandedItemIds`
178
+
179
+ Mutation and lookup methods:
180
+
181
+ - `storeNavigation()` and `deleteNavigation()`
182
+ - `setActiveItem()` and `clearActiveItem()`
183
+ - `expandItem()`, `collapseItem()`, `toggleItemExpanded()`, and `clearExpandedItems()`
184
+ - `getNavigation()`, `getActiveItem()`, `getFlatNavigation()`, `getItem()`, and `getItemParent()`
185
+
186
+ ## Styling Notes
187
+
188
+ - Pass Tailwind utility classes or other class names through the item `classes` and `badge.classes` fields when you need local visual overrides.
189
+ - Icons are resolved from Lucide. Use names such as `layout-dashboard`, `folders`, `settings-2`, or valid Lucide aliases.
190
+ - Active state depends on Angular Router. Use `exactMatch` or `isActiveMatchOptions` when the default subset matching is too broad.
191
+
192
+ ## Troubleshooting
193
+
194
+ ### Nothing renders
195
+
196
+ - Confirm the component receives a non-empty `navigation` input.
197
+ - If a horizontal navigation intentionally relies on service fallback, call `NavigationService.storeNavigation()` before it renders.
198
+ - Check whether `isHidden` returns `true` for the affected items.
199
+
200
+ ### Icons do not appear
201
+
202
+ - Use Lucide icon names or aliases, not Material icon names.
203
+ - Check the `icon` value on the affected item.
204
+
205
+ ### Active state is wrong
206
+
207
+ - Verify Router is configured and the application uses the expected route paths.
208
+ - Tune `exactMatch` or `isActiveMatchOptions` for the affected items.
209
+
210
+ ## Notes For Contributors
211
+
212
+ - Keep `@ojiepermana/angular/navigation` focused on the item model, helpers, and `NavigationService`.
213
+ - Keep render components in `@ojiepermana/angular/navigation/vertical` and `@ojiepermana/angular/navigation/horizontal`.
214
+ - Move shared implementation helpers behind `@ojiepermana/angular/internal` instead of reaching across entry point boundaries with relative imports.
215
+ - Treat `projects/library/navigation/shared` as a local compatibility layer for tests and source organization, not as consumer API.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ojiepermana/angular",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,6 +34,18 @@
34
34
  "types": "./types/ojiepermana-angular-layout.d.ts",
35
35
  "default": "./fesm2022/ojiepermana-angular-layout.mjs"
36
36
  },
37
+ "./navigation": {
38
+ "types": "./types/ojiepermana-angular-navigation.d.ts",
39
+ "default": "./fesm2022/ojiepermana-angular-navigation.mjs"
40
+ },
41
+ "./navigation/horizontal": {
42
+ "types": "./types/ojiepermana-angular-navigation-horizontal.d.ts",
43
+ "default": "./fesm2022/ojiepermana-angular-navigation-horizontal.mjs"
44
+ },
45
+ "./navigation/vertical": {
46
+ "types": "./types/ojiepermana-angular-navigation-vertical.d.ts",
47
+ "default": "./fesm2022/ojiepermana-angular-navigation-vertical.mjs"
48
+ },
37
49
  "./shell": {
38
50
  "types": "./types/ojiepermana-angular-shell.d.ts",
39
51
  "default": "./fesm2022/ojiepermana-angular-shell.mjs"
package/theme/README.md CHANGED
@@ -310,10 +310,7 @@ For a package consumer, use the published aggregate bundle instead:
310
310
 
311
311
  ```ts
312
312
  import { ChangeDetectionStrategy, Component } from '@angular/core';
313
- import {
314
- LayoutContainerSwitcherComponent,
315
- LayoutVerticalComponent,
316
- } from '@ojiepermana/angular/layout';
313
+ import { LayoutContainerSwitcherComponent, LayoutVerticalComponent } from '@ojiepermana/angular/layout';
317
314
  import {
318
315
  StyleSwitcherComponent,
319
316
  ColorPickerComponent,
@@ -28,11 +28,7 @@
28
28
  --mat-sys-on-surface: var(--container-foreground);
29
29
  --mat-sys-surface-container: var(--overlay-surface);
30
30
  --mat-sys-surface-container-high: var(--overlay-surface);
31
- --mat-sys-surface-container-highest: color-mix(
32
- in oklab,
33
- var(--overlay-surface) 90%,
34
- var(--muted)
35
- );
31
+ --mat-sys-surface-container-highest: color-mix(in oklab, var(--overlay-surface) 90%, var(--muted));
36
32
  --mat-sys-surface-variant: var(--data-header-surface);
37
33
  --mat-sys-on-surface-variant: var(--data-header-foreground);
38
34
  --mat-sys-inverse-surface: var(--inverse);
@@ -79,11 +79,7 @@ horizontal[data-layout-mode='horizontal'] > layout > :is(content, shell-content)
79
79
  min-block-size: 0;
80
80
  overflow: auto;
81
81
  background-color: var(--background);
82
- background-image: linear-gradient(
83
- 180deg,
84
- color-mix(in oklab, var(--background) 94%, white 6%),
85
- var(--background)
86
- );
82
+ background-image: linear-gradient(180deg, color-mix(in oklab, var(--background) 94%, white 6%), var(--background));
87
83
  color: var(--foreground);
88
84
  transition:
89
85
  background-color var(--ngt-motion-duration-medium) var(--ngt-motion-ease-standard),
@@ -107,11 +103,7 @@ horizontal[data-layout-mode='horizontal'] > layout > :is(content, shell-content)
107
103
  grid-template-columns: 1fr;
108
104
  }
109
105
 
110
- horizontal[data-layout-mode='horizontal']
111
- > layout
112
- > :is(content, shell-content)
113
- > header
114
- > panel {
106
+ horizontal[data-layout-mode='horizontal'] > layout > :is(content, shell-content) > header > panel {
115
107
  justify-content: flex-start;
116
108
  }
117
109
  }
@@ -53,11 +53,7 @@ vertical[data-layout-mode='vertical'] > layout > :is(content, shell-content) > m
53
53
  min-block-size: 0;
54
54
  overflow: auto;
55
55
  background-color: var(--background);
56
- background-image: linear-gradient(
57
- 180deg,
58
- color-mix(in oklab, var(--background) 94%, white 6%),
59
- var(--background)
60
- );
56
+ background-image: linear-gradient(180deg, color-mix(in oklab, var(--background) 94%, white 6%), var(--background));
61
57
  color: var(--foreground);
62
58
  transition:
63
59
  background-color var(--ngt-motion-duration-medium) var(--ngt-motion-ease-standard),
@@ -70,7 +66,9 @@ vertical[data-layout-mode='vertical'] > layout > :is(content, shell-content) > m
70
66
  }
71
67
 
72
68
  vertical[data-layout-mode='vertical'] > layout > :is(content, shell-content) > aside {
69
+ flex: 0 0 var(--layout-sidebar-width);
73
70
  inline-size: var(--layout-sidebar-width);
71
+ min-inline-size: var(--layout-sidebar-width);
74
72
  border-bottom: 0;
75
73
  border-right: 1px solid var(--sidebar-chrome-border);
76
74
  }
@@ -25,15 +25,13 @@
25
25
  --shell-foreground: var(--card-foreground);
26
26
  --shell-border: var(--border);
27
27
  --shell-shadow:
28
- rgb(0 0 0 / 0.14) 0 28px 70px, rgb(0 0 0 / 0.1) 0 14px 32px,
29
- oklab(0.263084 -0.00230259 0.0124794 / 0.1) 0 0 0 1px;
28
+ rgb(0 0 0 / 0.14) 0 28px 70px, rgb(0 0 0 / 0.1) 0 14px 32px, oklab(0.263084 -0.00230259 0.0124794 / 0.1) 0 0 0 1px;
30
29
  --shell-backdrop: var(--backdrop);
31
30
  --surface-elevated: var(--popover);
32
31
  --surface-elevated-foreground: var(--popover-foreground);
33
32
  --surface-elevated-border: oklab(0.263084 -0.00230259 0.0124794 / 0.2);
34
33
  --surface-elevated-shadow:
35
- rgb(0 0 0 / 0.12) 0 24px 52px, rgb(0 0 0 / 0.08) 0 10px 24px,
36
- oklab(0.263084 -0.00230259 0.0124794 / 0.1) 0 0 0 1px;
34
+ rgb(0 0 0 / 0.12) 0 24px 52px, rgb(0 0 0 / 0.08) 0 10px 24px, oklab(0.263084 -0.00230259 0.0124794 / 0.1) 0 0 0 1px;
37
35
  }
38
36
 
39
37
  .dark[data-theme-style='flat'] {
@@ -54,8 +52,7 @@
54
52
  --sidebar-primary-foreground: var(--foreground);
55
53
  --sidebar-accent: color-mix(in oklab, var(--theme-primary) 18%, var(--sidebar));
56
54
  --sidebar-accent-foreground: var(--foreground);
57
- --shell-shadow:
58
- rgb(0 0 0 / 0.44) 0 28px 70px, rgb(0 0 0 / 0.28) 0 14px 32px, rgb(235 231 222 / 0.08) 0 0 0 1px;
55
+ --shell-shadow: rgb(0 0 0 / 0.44) 0 28px 70px, rgb(0 0 0 / 0.28) 0 14px 32px, rgb(235 231 222 / 0.08) 0 0 0 1px;
59
56
  --surface-elevated: #2b2820;
60
57
  --surface-elevated-foreground: var(--foreground);
61
58
  --surface-elevated-border: rgb(235 231 222 / 0.12);
@@ -7,13 +7,7 @@
7
7
  ui-sans-serif,
8
8
  sans-serif
9
9
  );
10
- --typeface-brand: var(
11
- --theme-style-glass-brand-font,
12
- ui-rounded,
13
- 'Avenir Next',
14
- 'Segoe UI',
15
- sans-serif
16
- );
10
+ --typeface-brand: var(--theme-style-glass-brand-font, ui-rounded, 'Avenir Next', 'Segoe UI', sans-serif);
17
11
  --typeface-mono: var(
18
12
  --theme-style-glass-mono-font,
19
13
  'SFMono-Regular',
@@ -1,2 +1,2 @@
1
1
  @import './flat.css';
2
- @import './glass.css';
2
+ @import './glass.css';
@@ -3,6 +3,24 @@
3
3
  --nav-surface: color-mix(in oklab, var(--shell-surface) 92%, transparent);
4
4
  --nav-foreground: var(--shell-foreground);
5
5
  --nav-border: var(--shell-border);
6
+ --nav-font-family: var(--typeface-plain);
7
+ --nav-item-font-size: 0.875rem;
8
+ --nav-item-line-height: 1.25rem;
9
+ --nav-item-font-weight: 500;
10
+ --nav-item-active-font-weight: 600;
11
+ --nav-subtitle-font-size: 0.75rem;
12
+ --nav-subtitle-line-height: 1rem;
13
+ --nav-subtitle-font-weight: 400;
14
+ --nav-badge-font-size: 0.75rem;
15
+ --nav-badge-line-height: 1rem;
16
+ --nav-badge-font-weight: 600;
17
+ --nav-group-title-font-size: 0.75rem;
18
+ --nav-group-title-line-height: 1rem;
19
+ --nav-group-title-font-weight: 600;
20
+ --nav-group-title-letter-spacing: 0.08em;
21
+ --nav-group-subtitle-font-size: 0.75rem;
22
+ --nav-group-subtitle-line-height: 1rem;
23
+ --nav-group-subtitle-font-weight: 400;
6
24
  --nav-item-hover-surface: var(--tertiary-container);
7
25
  --nav-item-hover-foreground: var(--tertiary-container-foreground);
8
26
  --nav-item-active-surface: var(--secondary-container);
@@ -87,8 +87,7 @@
87
87
 
88
88
  /* Keep these radius tokens in :root as well so non-Tailwind consumers get the same values as @theme. */
89
89
  :root {
90
- --typeface-plain:
91
- ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
90
+ --typeface-plain: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
92
91
  --typeface-brand: var(--typeface-plain);
93
92
  --typeface-mono: 'SFMono-Regular', 'Cascadia Mono', 'Liberation Mono', ui-monospace, monospace;
94
93
  --radius: 0.75rem;
@@ -115,7 +114,7 @@
115
114
  --layout-shell-max-width: 100%;
116
115
  --layout-shell-padding: 0rem;
117
116
  --layout-shell-radius: 0rem;
118
- --layout-sidebar-width: 17rem;
117
+ --layout-sidebar-width: 280px;
119
118
  --layout-header-height: 3.75rem;
120
119
  --layout-header-display: grid;
121
120
  --layout-sidebar-display: flex;
@@ -131,9 +130,7 @@
131
130
  text-decoration-color var(--ngt-motion-duration-fast) var(--ngt-motion-ease-standard),
132
131
  backdrop-filter var(--ngt-motion-duration-medium) var(--ngt-motion-ease-standard);
133
132
  --ngt-shell-transition:
134
- var(--ngt-chrome-transition),
135
- border-radius var(--ngt-motion-duration-medium) var(--ngt-motion-ease-standard);
133
+ var(--ngt-chrome-transition), border-radius var(--ngt-motion-duration-medium) var(--ngt-motion-ease-standard);
136
134
  --ngt-control-transition:
137
- var(--ngt-chrome-transition),
138
- transform var(--ngt-motion-duration-fast) var(--ngt-motion-ease-standard);
135
+ var(--ngt-chrome-transition), transform var(--ngt-motion-duration-fast) var(--ngt-motion-ease-standard);
139
136
  }
@@ -1,4 +1,7 @@
1
1
  import * as _angular_core from '@angular/core';
2
+ import { TemplateRef } from '@angular/core';
3
+ import { LucideIcon } from '@lucide/angular';
4
+ import { NavigationItem } from '@ojiepermana/angular/navigation';
2
5
 
3
6
  declare const libraryLucideConfigProvider: _angular_core.Provider;
4
7
 
@@ -23,4 +26,64 @@ declare class LocalStorageStateAdapter<Axis extends string> {
23
26
  private legacyKey;
24
27
  }
25
28
 
26
- export { LocalStorageStateAdapter, libraryLucideConfigProvider };
29
+ type NavigationItemContentVariant = 'horizontal' | 'vertical' | 'vertical-group';
30
+ declare class NavigationItemContent {
31
+ item: _angular_core.InputSignal<NavigationItem>;
32
+ level: _angular_core.InputSignal<number>;
33
+ variant: _angular_core.InputSignal<NavigationItemContentVariant>;
34
+ protected readonly resolvedIcon: _angular_core.Signal<LucideIcon | null>;
35
+ protected readonly horizontalIconClass: _angular_core.Signal<string | null>;
36
+ protected readonly verticalIconClass: _angular_core.Signal<string | null>;
37
+ protected readonly horizontalTitleClass: _angular_core.Signal<string | null>;
38
+ protected readonly titleClass: _angular_core.Signal<string | null>;
39
+ protected readonly subtitleClass: _angular_core.Signal<string | null>;
40
+ protected readonly horizontalBadgeClass: _angular_core.Signal<string | null>;
41
+ protected readonly verticalBadgeClass: _angular_core.Signal<string | null>;
42
+ protected readonly titleContainerClass: _angular_core.Signal<"kit-navigation-group-title" | "kit-navigation-item-title">;
43
+ protected readonly subtitleContainerClass: _angular_core.Signal<"kit-navigation-group-subtitle" | "kit-navigation-item-subtitle">;
44
+ private joinClasses;
45
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NavigationItemContent, never>;
46
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NavigationItemContent, "navigation-item-content", never, { "item": { "alias": "item"; "required": true; "isSignal": true; }; "level": { "alias": "level"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
47
+ }
48
+
49
+ type NavigationTreeTemplateData = Record<string, unknown>;
50
+ interface NavigationTreeItemContext {
51
+ $implicit: NavigationItem;
52
+ level: number;
53
+ parentKey: string;
54
+ isLast: boolean;
55
+ data: NavigationTreeTemplateData | null;
56
+ }
57
+ declare class NavigationTreeOutlet {
58
+ items: _angular_core.InputSignal<NavigationItem[]>;
59
+ level: _angular_core.InputSignal<number>;
60
+ parentKey: _angular_core.InputSignal<string>;
61
+ data: _angular_core.InputSignal<NavigationTreeTemplateData | null>;
62
+ branchTemplate: _angular_core.InputSignal<TemplateRef<NavigationTreeItemContext>>;
63
+ leafTemplate: _angular_core.InputSignal<TemplateRef<NavigationTreeItemContext>>;
64
+ groupTemplate: _angular_core.InputSignal<TemplateRef<NavigationTreeItemContext>>;
65
+ dividerTemplate: _angular_core.InputSignal<TemplateRef<NavigationTreeItemContext> | null>;
66
+ spacerTemplate: _angular_core.InputSignal<TemplateRef<NavigationTreeItemContext> | null>;
67
+ trackByFn: _angular_core.InputSignal<(index: number, item: NavigationItem) => string | number | undefined>;
68
+ shouldRenderItemFn: _angular_core.InputSignal<(item: NavigationItem) => boolean>;
69
+ hasChildrenFn: _angular_core.InputSignal<(item: NavigationItem) => boolean>;
70
+ resolveParentKeyFn: _angular_core.InputSignal<(parentKey: string, item: NavigationItem) => string>;
71
+ trackItem(index: number, item: NavigationItem): string | number | undefined;
72
+ shouldRender(item: NavigationItem): boolean;
73
+ hasChildren(item: NavigationItem): boolean;
74
+ resolveParentKey(parentKey: string, item: NavigationItem): string;
75
+ templateContext(item: NavigationItem, isLast: boolean): NavigationTreeItemContext;
76
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NavigationTreeOutlet, never>;
77
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NavigationTreeOutlet, "navigation-tree-outlet", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "level": { "alias": "level"; "required": false; "isSignal": true; }; "parentKey": { "alias": "parentKey"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "branchTemplate": { "alias": "branchTemplate"; "required": true; "isSignal": true; }; "leafTemplate": { "alias": "leafTemplate"; "required": true; "isSignal": true; }; "groupTemplate": { "alias": "groupTemplate"; "required": true; "isSignal": true; }; "dividerTemplate": { "alias": "dividerTemplate"; "required": false; "isSignal": true; }; "spacerTemplate": { "alias": "spacerTemplate"; "required": false; "isSignal": true; }; "trackByFn": { "alias": "trackByFn"; "required": false; "isSignal": true; }; "shouldRenderItemFn": { "alias": "shouldRenderItemFn"; "required": false; "isSignal": true; }; "hasChildrenFn": { "alias": "hasChildrenFn"; "required": false; "isSignal": true; }; "resolveParentKeyFn": { "alias": "resolveParentKeyFn"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
78
+ }
79
+
80
+ type NavigationExpandedItemsByParent = Record<string, string>;
81
+ declare function trackNavigationTreeItem(index: number, item: NavigationItem): string | number | undefined;
82
+ declare function getNavigationTreePathKey(parentKey: string, item: NavigationItem): string;
83
+ declare function isNavigationTreeItemExpanded(expandedByParent: NavigationExpandedItemsByParent, parentKey: string, item: NavigationItem): boolean;
84
+ declare function toggleNavigationTreeItemExpanded(expandedByParent: NavigationExpandedItemsByParent, parentKey: string, item: NavigationItem): NavigationExpandedItemsByParent;
85
+ declare function hasActiveNavigationDescendant(item: NavigationItem, isItemActive: (item: NavigationItem) => boolean): boolean;
86
+ declare function isNavigationTreeDescendant(parent: NavigationItem, item: NavigationItem): boolean;
87
+
88
+ export { LocalStorageStateAdapter, NavigationItemContent, NavigationTreeOutlet, getNavigationTreePathKey, hasActiveNavigationDescendant, isNavigationTreeDescendant, isNavigationTreeItemExpanded, libraryLucideConfigProvider, toggleNavigationTreeItemExpanded, trackNavigationTreeItem };
89
+ export type { NavigationExpandedItemsByParent, NavigationTreeItemContext, NavigationTreeTemplateData };