@ngstarter-ui/components 1.0.46 → 1.0.47

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.
@@ -1157,6 +1157,560 @@ function provideNgsTheme(options = {}) {
1157
1157
  };
1158
1158
  }
1159
1159
 
1160
+ const LIGHT_TEXT = '#ffffff';
1161
+ const DARK_TEXT = '#0f172a';
1162
+ const NGS_GENERATED_THEME_PROPERTY_NAMES = [
1163
+ '--ngs-color-primary-seed',
1164
+ '--ngs-color-primary',
1165
+ '--ngs-color-on-primary',
1166
+ '--ngs-color-primary-container',
1167
+ '--ngs-color-on-primary-container',
1168
+ '--ngs-color-secondary',
1169
+ '--ngs-color-on-secondary',
1170
+ '--ngs-color-secondary-container',
1171
+ '--ngs-color-on-secondary-container',
1172
+ '--ngs-color-tertiary',
1173
+ '--ngs-color-on-tertiary',
1174
+ '--ngs-color-tertiary-container',
1175
+ '--ngs-color-on-tertiary-container',
1176
+ '--ngs-color-info',
1177
+ '--ngs-color-on-info',
1178
+ '--ngs-color-info-container',
1179
+ '--ngs-color-on-info-container',
1180
+ '--ngs-color-danger',
1181
+ '--ngs-color-on-danger',
1182
+ '--ngs-color-danger-container',
1183
+ '--ngs-color-on-danger-container',
1184
+ '--ngs-color-danger-container-lowest',
1185
+ '--ngs-color-danger-container-low',
1186
+ '--ngs-color-danger-container-high',
1187
+ '--ngs-color-danger-container-highest',
1188
+ '--ngs-color-success',
1189
+ '--ngs-color-on-success',
1190
+ '--ngs-color-success-container',
1191
+ '--ngs-color-on-success-container',
1192
+ '--ngs-color-warning',
1193
+ '--ngs-color-on-warning',
1194
+ '--ngs-color-warning-container',
1195
+ '--ngs-color-on-warning-container',
1196
+ '--ngs-color-orange-container',
1197
+ '--ngs-color-on-orange-container',
1198
+ '--ngs-color-green-500',
1199
+ '--ngs-color-background',
1200
+ '--ngs-color-on-background',
1201
+ '--ngs-color-surface',
1202
+ '--ngs-color-surface-bright',
1203
+ '--ngs-color-on-surface',
1204
+ '--ngs-color-on-surface-variant',
1205
+ '--ngs-color-neutral-50',
1206
+ '--ngs-color-neutral-100',
1207
+ '--ngs-color-neutral-200',
1208
+ '--ngs-color-neutral-300',
1209
+ '--ngs-color-neutral-400',
1210
+ '--ngs-color-neutral-500',
1211
+ '--ngs-color-neutral-600',
1212
+ '--ngs-color-neutral-650',
1213
+ '--ngs-color-neutral-700',
1214
+ '--ngs-color-neutral-800',
1215
+ '--ngs-color-neutral-900',
1216
+ '--ngs-color-neutral-950',
1217
+ '--ngs-color-surface-container-lowest',
1218
+ '--ngs-color-surface-container-low',
1219
+ '--ngs-color-surface-container',
1220
+ '--ngs-color-surface-container-high',
1221
+ '--ngs-color-surface-container-highest',
1222
+ '--ngs-color-outline',
1223
+ '--ngs-color-outline-variant',
1224
+ '--ngs-color-border',
1225
+ '--ngs-color-faint',
1226
+ '--ngs-color-subtle',
1227
+ '--ngs-color-muted',
1228
+ '--ngs-color-emphasis',
1229
+ '--ngs-color-strong',
1230
+ '--ngs-state-hover-bg',
1231
+ '--ngs-state-active-bg',
1232
+ '--ngs-state-selected-bg',
1233
+ '--ngs-state-selected-color',
1234
+ '--ngs-state-focus-ring',
1235
+ '--ngs-state-disabled-bg',
1236
+ '--ngs-state-disabled-color',
1237
+ '--ngs-state-disabled-border',
1238
+ '--ngs-color-primary-100',
1239
+ '--ngs-color-primary-200',
1240
+ '--ngs-color-primary-300',
1241
+ '--ngs-color-primary-400',
1242
+ '--ngs-color-primary-500',
1243
+ '--ngs-color-primary-600',
1244
+ '--ngs-color-secondary-100',
1245
+ '--ngs-color-secondary-200',
1246
+ '--ngs-color-secondary-300',
1247
+ '--ngs-color-secondary-400',
1248
+ '--ngs-color-secondary-fixed',
1249
+ '--ngs-color-on-secondary-fixed',
1250
+ '--ngs-color-tertiary-100',
1251
+ '--ngs-color-tertiary-200',
1252
+ '--ngs-color-tertiary-300',
1253
+ '--ngs-color-tertiary-700',
1254
+ '--ngs-color-tertiary-800',
1255
+ '--ngs-button-tonal-bg',
1256
+ '--ngs-button-tonal-color',
1257
+ '--ngs-button-outlined-border',
1258
+ '--ngs-field-border-color',
1259
+ '--ngs-field-border-focus-color',
1260
+ '--ngs-field-filled-bg',
1261
+ '--ngs-dropdown-item-selected-bg',
1262
+ '--ngs-dropdown-item-selected-color',
1263
+ '--ngs-nav-item-active-color',
1264
+ '--ngs-nav-item-active-bg',
1265
+ '--ngs-nav-item-active-icon-color',
1266
+ ];
1267
+ function generateNgsThemeProperties(primaryColor, colorScheme = 'light') {
1268
+ const seed = parseColor(primaryColor);
1269
+ if (!seed) {
1270
+ return {
1271
+ '--ngs-color-primary-seed': primaryColor,
1272
+ '--ngs-color-primary': primaryColor,
1273
+ };
1274
+ }
1275
+ return colorScheme === 'dark'
1276
+ ? generateDarkThemeProperties(seed)
1277
+ : generateLightThemeProperties(seed);
1278
+ }
1279
+ function generateNgsThemeCssText(primaryColor, colorScheme = 'light') {
1280
+ return Object.entries(generateNgsThemeProperties(primaryColor, colorScheme))
1281
+ .map(([name, value]) => `${name}: ${value};`)
1282
+ .join('\n');
1283
+ }
1284
+ function generateLightThemeProperties(seed) {
1285
+ const source = rgbToHsl(seed);
1286
+ const primary = toHex(seed);
1287
+ const primaryContainer = colorFromTone(source, 93, 0.62);
1288
+ const secondary = colorFromTone(source, 36, 0.36, -8);
1289
+ const secondaryContainer = colorFromTone(source, 92, 0.28, -8);
1290
+ const tertiary = colorFromTone(source, 42, 0.72, 48);
1291
+ const tertiaryContainer = colorFromTone(source, 92, 0.42, 48);
1292
+ const info = colorFromTone(source, 48, 0.9, 8);
1293
+ const infoContainer = colorFromTone(source, 92, 0.38, 8);
1294
+ const status = makeStatusColors('light');
1295
+ const neutral = makeNeutralScale(source, 'light');
1296
+ const border = colorFromTone(source, 90, 0.08);
1297
+ const outline = colorFromTone(source, 56, 0.12);
1298
+ const outlineVariant = colorFromTone(source, 86, 0.08);
1299
+ return withSharedGeneratedProperties({
1300
+ '--ngs-color-primary': primary,
1301
+ '--ngs-color-primary-seed': primary,
1302
+ '--ngs-color-on-primary': readableOn(primary),
1303
+ '--ngs-color-primary-container': primaryContainer,
1304
+ '--ngs-color-on-primary-container': readableOn(primaryContainer, DARK_TEXT, primary),
1305
+ '--ngs-color-secondary': secondary,
1306
+ '--ngs-color-on-secondary': readableOn(secondary),
1307
+ '--ngs-color-secondary-container': secondaryContainer,
1308
+ '--ngs-color-on-secondary-container': readableOn(secondaryContainer, DARK_TEXT, secondary),
1309
+ '--ngs-color-tertiary': tertiary,
1310
+ '--ngs-color-on-tertiary': readableOn(tertiary),
1311
+ '--ngs-color-tertiary-container': tertiaryContainer,
1312
+ '--ngs-color-on-tertiary-container': readableOn(tertiaryContainer, DARK_TEXT, tertiary),
1313
+ '--ngs-color-info': info,
1314
+ '--ngs-color-on-info': readableOn(info),
1315
+ '--ngs-color-info-container': infoContainer,
1316
+ '--ngs-color-on-info-container': readableOn(infoContainer, DARK_TEXT, info),
1317
+ ...status,
1318
+ '--ngs-color-background': neutral[0],
1319
+ '--ngs-color-on-background': neutral[11],
1320
+ '--ngs-color-surface': neutral[1],
1321
+ '--ngs-color-surface-bright': '#ffffff',
1322
+ '--ngs-color-on-surface': neutral[11],
1323
+ '--ngs-color-on-surface-variant': neutral[6],
1324
+ '--ngs-color-neutral-50': neutral[0],
1325
+ '--ngs-color-neutral-100': neutral[1],
1326
+ '--ngs-color-neutral-200': neutral[2],
1327
+ '--ngs-color-neutral-300': neutral[3],
1328
+ '--ngs-color-neutral-400': neutral[4],
1329
+ '--ngs-color-neutral-500': neutral[5],
1330
+ '--ngs-color-neutral-600': neutral[6],
1331
+ '--ngs-color-neutral-650': neutral[7],
1332
+ '--ngs-color-neutral-700': neutral[8],
1333
+ '--ngs-color-neutral-800': neutral[9],
1334
+ '--ngs-color-neutral-900': neutral[10],
1335
+ '--ngs-color-neutral-950': neutral[11],
1336
+ '--ngs-color-surface-container-lowest': '#ffffff',
1337
+ '--ngs-color-surface-container-low': neutral[0],
1338
+ '--ngs-color-surface-container': neutral[1],
1339
+ '--ngs-color-surface-container-high': neutral[2],
1340
+ '--ngs-color-surface-container-highest': neutral[3],
1341
+ '--ngs-color-outline': outline,
1342
+ '--ngs-color-outline-variant': outlineVariant,
1343
+ '--ngs-color-border': border,
1344
+ '--ngs-color-faint': neutral[1],
1345
+ '--ngs-color-subtle': neutral[2],
1346
+ '--ngs-color-muted': neutral[3],
1347
+ '--ngs-color-emphasis': neutral[5],
1348
+ '--ngs-color-strong': neutral[6],
1349
+ '--ngs-state-selected-color': primary,
1350
+ '--ngs-button-tonal-bg': secondaryContainer,
1351
+ '--ngs-button-tonal-color': readableOn(secondaryContainer, DARK_TEXT, secondary),
1352
+ '--ngs-button-outlined-border': outlineVariant,
1353
+ '--ngs-field-border-color': outlineVariant,
1354
+ '--ngs-field-border-focus-color': primary,
1355
+ '--ngs-field-filled-bg': neutral[1],
1356
+ '--ngs-dropdown-item-selected-bg': primaryContainer,
1357
+ '--ngs-dropdown-item-selected-color': readableOn(primaryContainer, DARK_TEXT, primary),
1358
+ '--ngs-nav-item-active-color': primary,
1359
+ '--ngs-nav-item-active-bg': primaryContainer,
1360
+ '--ngs-nav-item-active-icon-color': primary,
1361
+ });
1362
+ }
1363
+ function generateDarkThemeProperties(seed) {
1364
+ const source = rgbToHsl(seed);
1365
+ const primary = colorFromTone(source, 76, 0.82);
1366
+ const primaryContainer = colorFromTone(source, 28, 0.78);
1367
+ const secondary = colorFromTone(source, 78, 0.36, -8);
1368
+ const secondaryContainer = colorFromTone(source, 28, 0.3, -8);
1369
+ const tertiary = colorFromTone(source, 78, 0.62, 48);
1370
+ const tertiaryContainer = colorFromTone(source, 30, 0.52, 48);
1371
+ const info = colorFromTone(source, 76, 0.84, 8);
1372
+ const infoContainer = colorFromTone(source, 30, 0.62, 8);
1373
+ const status = makeStatusColors('dark');
1374
+ const neutral = makeNeutralScale(source, 'dark');
1375
+ const border = colorFromTone(source, 22, 0.08);
1376
+ const outline = colorFromTone(source, 66, 0.12);
1377
+ const outlineVariant = colorFromTone(source, 28, 0.08);
1378
+ return withSharedGeneratedProperties({
1379
+ '--ngs-color-primary': primary,
1380
+ '--ngs-color-primary-seed': toHex(seed),
1381
+ '--ngs-color-on-primary': readableOn(primary),
1382
+ '--ngs-color-primary-container': primaryContainer,
1383
+ '--ngs-color-on-primary-container': readableOn(primaryContainer),
1384
+ '--ngs-color-secondary': secondary,
1385
+ '--ngs-color-on-secondary': readableOn(secondary),
1386
+ '--ngs-color-secondary-container': secondaryContainer,
1387
+ '--ngs-color-on-secondary-container': readableOn(secondaryContainer),
1388
+ '--ngs-color-tertiary': tertiary,
1389
+ '--ngs-color-on-tertiary': readableOn(tertiary),
1390
+ '--ngs-color-tertiary-container': tertiaryContainer,
1391
+ '--ngs-color-on-tertiary-container': readableOn(tertiaryContainer),
1392
+ '--ngs-color-info': info,
1393
+ '--ngs-color-on-info': readableOn(info),
1394
+ '--ngs-color-info-container': infoContainer,
1395
+ '--ngs-color-on-info-container': readableOn(infoContainer),
1396
+ ...status,
1397
+ '--ngs-color-background': neutral[0],
1398
+ '--ngs-color-on-background': neutral[11],
1399
+ '--ngs-color-surface': neutral[1],
1400
+ '--ngs-color-surface-bright': neutral[2],
1401
+ '--ngs-color-on-surface': neutral[11],
1402
+ '--ngs-color-on-surface-variant': neutral[8],
1403
+ '--ngs-color-neutral-50': neutral[0],
1404
+ '--ngs-color-neutral-100': neutral[1],
1405
+ '--ngs-color-neutral-200': neutral[2],
1406
+ '--ngs-color-neutral-300': neutral[3],
1407
+ '--ngs-color-neutral-400': neutral[4],
1408
+ '--ngs-color-neutral-500': neutral[5],
1409
+ '--ngs-color-neutral-600': neutral[6],
1410
+ '--ngs-color-neutral-650': neutral[7],
1411
+ '--ngs-color-neutral-700': neutral[8],
1412
+ '--ngs-color-neutral-800': neutral[9],
1413
+ '--ngs-color-neutral-900': neutral[10],
1414
+ '--ngs-color-neutral-950': neutral[11],
1415
+ '--ngs-color-surface-container-lowest': neutral[0],
1416
+ '--ngs-color-surface-container-low': neutral[1],
1417
+ '--ngs-color-surface-container': neutral[2],
1418
+ '--ngs-color-surface-container-high': neutral[3],
1419
+ '--ngs-color-surface-container-highest': neutral[4],
1420
+ '--ngs-color-outline': outline,
1421
+ '--ngs-color-outline-variant': outlineVariant,
1422
+ '--ngs-color-border': border,
1423
+ '--ngs-color-faint': neutral[1],
1424
+ '--ngs-color-subtle': neutral[2],
1425
+ '--ngs-color-muted': neutral[3],
1426
+ '--ngs-color-emphasis': neutral[7],
1427
+ '--ngs-color-strong': neutral[9],
1428
+ '--ngs-state-selected-color': primary,
1429
+ '--ngs-button-tonal-bg': secondaryContainer,
1430
+ '--ngs-button-tonal-color': readableOn(secondaryContainer),
1431
+ '--ngs-button-outlined-border': outlineVariant,
1432
+ '--ngs-field-border-color': outlineVariant,
1433
+ '--ngs-field-border-focus-color': primary,
1434
+ '--ngs-field-filled-bg': neutral[2],
1435
+ '--ngs-dropdown-item-selected-bg': primaryContainer,
1436
+ '--ngs-dropdown-item-selected-color': readableOn(primaryContainer),
1437
+ '--ngs-nav-item-active-color': primary,
1438
+ '--ngs-nav-item-active-bg': primaryContainer,
1439
+ '--ngs-nav-item-active-icon-color': primary,
1440
+ });
1441
+ }
1442
+ function withSharedGeneratedProperties(properties) {
1443
+ return {
1444
+ ...properties,
1445
+ '--ngs-state-hover-bg': 'color-mix(in srgb, var(--ngs-color-on-surface), transparent 94%)',
1446
+ '--ngs-state-active-bg': 'color-mix(in srgb, var(--ngs-color-on-surface), transparent 90%)',
1447
+ '--ngs-state-selected-bg': 'color-mix(in srgb, var(--ngs-color-primary), transparent 88%)',
1448
+ '--ngs-state-focus-ring': 'var(--ngs-field-border-focus-color)',
1449
+ '--ngs-state-disabled-bg': 'color-mix(in srgb, var(--ngs-color-on-surface), transparent 95%)',
1450
+ '--ngs-state-disabled-color': 'color-mix(in srgb, var(--ngs-color-on-surface), transparent 62%)',
1451
+ '--ngs-state-disabled-border': 'color-mix(in srgb, var(--ngs-color-on-surface), transparent 90%)',
1452
+ '--ngs-color-primary-100': 'color-mix(in srgb, var(--ngs-color-primary), transparent 90%)',
1453
+ '--ngs-color-primary-200': 'color-mix(in srgb, var(--ngs-color-primary), transparent 80%)',
1454
+ '--ngs-color-primary-300': 'color-mix(in srgb, var(--ngs-color-primary), transparent 70%)',
1455
+ '--ngs-color-primary-400': 'color-mix(in srgb, var(--ngs-color-primary), transparent 60%)',
1456
+ '--ngs-color-primary-500': 'color-mix(in srgb, var(--ngs-color-primary), transparent 50%)',
1457
+ '--ngs-color-primary-600': 'color-mix(in srgb, var(--ngs-color-primary), transparent 40%)',
1458
+ '--ngs-color-secondary-100': 'color-mix(in srgb, var(--ngs-color-secondary), transparent 90%)',
1459
+ '--ngs-color-secondary-200': 'color-mix(in srgb, var(--ngs-color-secondary), transparent 80%)',
1460
+ '--ngs-color-secondary-300': 'color-mix(in srgb, var(--ngs-color-secondary), transparent 70%)',
1461
+ '--ngs-color-secondary-400': 'color-mix(in srgb, var(--ngs-color-secondary), transparent 60%)',
1462
+ '--ngs-color-secondary-fixed': 'var(--ngs-color-secondary-container)',
1463
+ '--ngs-color-on-secondary-fixed': 'var(--ngs-color-on-secondary-container)',
1464
+ '--ngs-color-tertiary-100': 'color-mix(in srgb, var(--ngs-color-tertiary), transparent 90%)',
1465
+ '--ngs-color-tertiary-200': 'color-mix(in srgb, var(--ngs-color-tertiary), transparent 80%)',
1466
+ '--ngs-color-tertiary-300': 'color-mix(in srgb, var(--ngs-color-tertiary), transparent 70%)',
1467
+ '--ngs-color-tertiary-700': 'color-mix(in srgb, var(--ngs-color-tertiary), #000000 35%)',
1468
+ '--ngs-color-tertiary-800': 'color-mix(in srgb, var(--ngs-color-tertiary), #000000 50%)',
1469
+ };
1470
+ }
1471
+ function makeNeutralScale(source, colorScheme) {
1472
+ const saturation = Math.min(source.s * 0.12, 8);
1473
+ const lightness = colorScheme === 'dark'
1474
+ ? [5, 8, 12, 17, 24, 39, 55, 64, 73, 84, 92, 97]
1475
+ : [98, 96, 91, 84, 72, 56, 43, 36, 28, 19, 11, 4];
1476
+ return lightness.map(l => hslToHex({ h: source.h, s: saturation, l }));
1477
+ }
1478
+ function makeStatusColors(colorScheme) {
1479
+ if (colorScheme === 'dark') {
1480
+ return {
1481
+ '--ngs-color-danger': '#f87171',
1482
+ '--ngs-color-on-danger': '#450a0a',
1483
+ '--ngs-color-danger-container': '#7f1d1d',
1484
+ '--ngs-color-on-danger-container': '#fef2f2',
1485
+ '--ngs-color-danger-container-lowest': '#1f0707',
1486
+ '--ngs-color-danger-container-low': '#2f0b0b',
1487
+ '--ngs-color-danger-container-high': '#5f1717',
1488
+ '--ngs-color-danger-container-highest': '#7f1d1d',
1489
+ '--ngs-color-success': '#4ade80',
1490
+ '--ngs-color-on-success': '#052e16',
1491
+ '--ngs-color-success-container': '#166534',
1492
+ '--ngs-color-on-success-container': '#dcfce7',
1493
+ '--ngs-color-warning': '#fbbf24',
1494
+ '--ngs-color-on-warning': '#451a03',
1495
+ '--ngs-color-warning-container': '#78350f',
1496
+ '--ngs-color-on-warning-container': '#fef3c7',
1497
+ '--ngs-color-orange-container': '#78350f',
1498
+ '--ngs-color-on-orange-container': '#fef3c7',
1499
+ '--ngs-color-green-500': '#4ade80',
1500
+ };
1501
+ }
1502
+ return {
1503
+ '--ngs-color-danger': '#dc2626',
1504
+ '--ngs-color-on-danger': '#ffffff',
1505
+ '--ngs-color-danger-container': '#fee2e2',
1506
+ '--ngs-color-on-danger-container': '#7f1d1d',
1507
+ '--ngs-color-danger-container-lowest': '#fffafa',
1508
+ '--ngs-color-danger-container-low': '#fef2f2',
1509
+ '--ngs-color-danger-container-high': '#fecaca',
1510
+ '--ngs-color-danger-container-highest': '#fca5a5',
1511
+ '--ngs-color-success': '#16a34a',
1512
+ '--ngs-color-on-success': '#ffffff',
1513
+ '--ngs-color-success-container': '#dcfce7',
1514
+ '--ngs-color-on-success-container': '#14532d',
1515
+ '--ngs-color-warning': '#d97706',
1516
+ '--ngs-color-on-warning': '#ffffff',
1517
+ '--ngs-color-warning-container': '#fef3c7',
1518
+ '--ngs-color-on-warning-container': '#78350f',
1519
+ '--ngs-color-orange-container': '#fef3c7',
1520
+ '--ngs-color-on-orange-container': '#78350f',
1521
+ '--ngs-color-green-500': '#16a34a',
1522
+ };
1523
+ }
1524
+ function colorFromTone(source, lightness, saturationMultiplier = 1, hueShift = 0) {
1525
+ return hslToHex({
1526
+ h: normalizeHue(source.h + hueShift),
1527
+ s: clamp(source.s * saturationMultiplier, 8, 92),
1528
+ l: lightness,
1529
+ });
1530
+ }
1531
+ function readableOn(color, dark = DARK_TEXT, light = LIGHT_TEXT) {
1532
+ const bg = parseColor(color);
1533
+ if (!bg) {
1534
+ return light;
1535
+ }
1536
+ const darkContrast = contrastRatio(bg, parseColor(dark) ?? { r: 15, g: 23, b: 42 });
1537
+ const lightContrast = contrastRatio(bg, parseColor(light) ?? { r: 255, g: 255, b: 255 });
1538
+ return darkContrast >= lightContrast ? dark : light;
1539
+ }
1540
+ function parseColor(color) {
1541
+ const value = color.trim().toLowerCase();
1542
+ if (value.startsWith('#')) {
1543
+ return parseHexColor(value);
1544
+ }
1545
+ if (value.startsWith('rgb(') || value.startsWith('rgba(')) {
1546
+ return parseRgbColor(value);
1547
+ }
1548
+ if (value.startsWith('hsl(') || value.startsWith('hsla(')) {
1549
+ return parseHslColor(value);
1550
+ }
1551
+ return null;
1552
+ }
1553
+ function parseHexColor(value) {
1554
+ const hex = value.slice(1);
1555
+ if (!/^[\da-f]+$/i.test(hex)) {
1556
+ return null;
1557
+ }
1558
+ if (hex.length === 3 || hex.length === 4) {
1559
+ return {
1560
+ r: parseInt(hex[0] + hex[0], 16),
1561
+ g: parseInt(hex[1] + hex[1], 16),
1562
+ b: parseInt(hex[2] + hex[2], 16),
1563
+ };
1564
+ }
1565
+ if (hex.length === 6 || hex.length === 8) {
1566
+ return {
1567
+ r: parseInt(hex.slice(0, 2), 16),
1568
+ g: parseInt(hex.slice(2, 4), 16),
1569
+ b: parseInt(hex.slice(4, 6), 16),
1570
+ };
1571
+ }
1572
+ return null;
1573
+ }
1574
+ function parseRgbColor(value) {
1575
+ const matches = value.match(/rgba?\(([^)]+)\)/);
1576
+ if (!matches) {
1577
+ return null;
1578
+ }
1579
+ const channels = matches[1]
1580
+ .replace(/\s*\/\s*[\d.]+%?\s*$/, '')
1581
+ .split(/[\s,]+/)
1582
+ .filter(Boolean)
1583
+ .slice(0, 3)
1584
+ .map(channel => parseFloat(channel));
1585
+ if (channels.length < 3 || channels.some(Number.isNaN)) {
1586
+ return null;
1587
+ }
1588
+ return {
1589
+ r: clamp(Math.round(channels[0]), 0, 255),
1590
+ g: clamp(Math.round(channels[1]), 0, 255),
1591
+ b: clamp(Math.round(channels[2]), 0, 255),
1592
+ };
1593
+ }
1594
+ function parseHslColor(value) {
1595
+ const matches = value.match(/hsla?\(([^)]+)\)/);
1596
+ if (!matches) {
1597
+ return null;
1598
+ }
1599
+ const channels = matches[1]
1600
+ .replace(/\s*\/\s*[\d.]+%?\s*$/, '')
1601
+ .split(/[\s,]+/)
1602
+ .filter(Boolean)
1603
+ .slice(0, 3);
1604
+ if (channels.length < 3) {
1605
+ return null;
1606
+ }
1607
+ const h = parseFloat(channels[0]);
1608
+ const s = parseFloat(channels[1]);
1609
+ const l = parseFloat(channels[2]);
1610
+ if ([h, s, l].some(Number.isNaN)) {
1611
+ return null;
1612
+ }
1613
+ return hslToRgb({ h, s, l });
1614
+ }
1615
+ function rgbToHsl({ r, g, b }) {
1616
+ const red = r / 255;
1617
+ const green = g / 255;
1618
+ const blue = b / 255;
1619
+ const max = Math.max(red, green, blue);
1620
+ const min = Math.min(red, green, blue);
1621
+ const delta = max - min;
1622
+ const lightness = (max + min) / 2;
1623
+ if (delta === 0) {
1624
+ return { h: 0, s: 0, l: lightness * 100 };
1625
+ }
1626
+ const saturation = delta / (1 - Math.abs(2 * lightness - 1));
1627
+ let hue = 0;
1628
+ if (max === red) {
1629
+ hue = ((green - blue) / delta) % 6;
1630
+ }
1631
+ else if (max === green) {
1632
+ hue = (blue - red) / delta + 2;
1633
+ }
1634
+ else {
1635
+ hue = (red - green) / delta + 4;
1636
+ }
1637
+ return {
1638
+ h: normalizeHue(hue * 60),
1639
+ s: saturation * 100,
1640
+ l: lightness * 100,
1641
+ };
1642
+ }
1643
+ function hslToRgb({ h, s, l }) {
1644
+ const saturation = clamp(s, 0, 100) / 100;
1645
+ const lightness = clamp(l, 0, 100) / 100;
1646
+ const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;
1647
+ const hue = normalizeHue(h) / 60;
1648
+ const x = chroma * (1 - Math.abs((hue % 2) - 1));
1649
+ const match = lightness - chroma / 2;
1650
+ let red = 0;
1651
+ let green = 0;
1652
+ let blue = 0;
1653
+ if (hue >= 0 && hue < 1) {
1654
+ red = chroma;
1655
+ green = x;
1656
+ }
1657
+ else if (hue >= 1 && hue < 2) {
1658
+ red = x;
1659
+ green = chroma;
1660
+ }
1661
+ else if (hue >= 2 && hue < 3) {
1662
+ green = chroma;
1663
+ blue = x;
1664
+ }
1665
+ else if (hue >= 3 && hue < 4) {
1666
+ green = x;
1667
+ blue = chroma;
1668
+ }
1669
+ else if (hue >= 4 && hue < 5) {
1670
+ red = x;
1671
+ blue = chroma;
1672
+ }
1673
+ else if (hue >= 5 && hue < 6) {
1674
+ red = chroma;
1675
+ blue = x;
1676
+ }
1677
+ return {
1678
+ r: Math.round((red + match) * 255),
1679
+ g: Math.round((green + match) * 255),
1680
+ b: Math.round((blue + match) * 255),
1681
+ };
1682
+ }
1683
+ function hslToHex(hsl) {
1684
+ return toHex(hslToRgb(hsl));
1685
+ }
1686
+ function toHex({ r, g, b }) {
1687
+ return `#${toHexChannel(r)}${toHexChannel(g)}${toHexChannel(b)}`;
1688
+ }
1689
+ function toHexChannel(value) {
1690
+ return clamp(Math.round(value), 0, 255).toString(16).padStart(2, '0');
1691
+ }
1692
+ function contrastRatio(first, second) {
1693
+ const firstLuminance = relativeLuminance(first);
1694
+ const secondLuminance = relativeLuminance(second);
1695
+ const lighter = Math.max(firstLuminance, secondLuminance);
1696
+ const darker = Math.min(firstLuminance, secondLuminance);
1697
+ return (lighter + 0.05) / (darker + 0.05);
1698
+ }
1699
+ function relativeLuminance({ r, g, b }) {
1700
+ return [r, g, b]
1701
+ .map(channel => {
1702
+ const value = channel / 255;
1703
+ return value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4);
1704
+ })
1705
+ .reduce((total, value, index) => total + value * [0.2126, 0.7152, 0.0722][index], 0);
1706
+ }
1707
+ function normalizeHue(hue) {
1708
+ return ((hue % 360) + 360) % 360;
1709
+ }
1710
+ function clamp(value, min, max) {
1711
+ return Math.min(max, Math.max(min, value));
1712
+ }
1713
+
1160
1714
  class ThemeManagerService {
1161
1715
  _document = inject(DOCUMENT);
1162
1716
  _window = this._document.defaultView;
@@ -1297,11 +1851,19 @@ class ThemeManagerService {
1297
1851
  root.setAttribute('data-ngs-theme', this._theme());
1298
1852
  root.setAttribute('data-ngs-color-scheme', this._colorScheme());
1299
1853
  root.setAttribute('data-ngs-radius', this._radius());
1300
- if (primaryColor && root.style) {
1301
- root.style.setProperty('--ngs-color-primary', primaryColor);
1854
+ if (!root.style) {
1855
+ return;
1302
1856
  }
1303
- else if (root.style) {
1304
- root.style.removeProperty('--ngs-color-primary');
1857
+ if (primaryColor) {
1858
+ for (const name of NGS_GENERATED_THEME_PROPERTY_NAMES) {
1859
+ root.style.removeProperty(name);
1860
+ }
1861
+ root.style.setProperty('--ngs-color-primary-seed', primaryColor);
1862
+ }
1863
+ else {
1864
+ for (const name of NGS_GENERATED_THEME_PROPERTY_NAMES) {
1865
+ root.style.removeProperty(name);
1866
+ }
1305
1867
  }
1306
1868
  }
1307
1869
  get _storageKey() {
@@ -1431,5 +1993,5 @@ function typedFromEvent(target, event, options) {
1431
1993
  * Generated bundle index. Do not edit.
1432
1994
  */
1433
1995
 
1434
- export { AUTOFOCUSABLE, AnalyticsService, AutoFocusDirective, DebounceTimeDirective, ENVIRONMENT, EnvironmentService, ErrorStateMatcher, FilterByPropertyPipe, FocusElementDirective, FormatFileSizePipe, GlobalStore, InactivityTrackerService, InitialsPipe, MutationObserverService, NGS_THEME_OPTIONS, OrderByPipe, PageTitleStrategyService, RIPPLE_GLOBAL_OPTIONS, ResizeObserverService, Ripple, RippleRef, RippleRenderer, RippleState, SafeHtmlPipe, SafeResourceUrlPipe, ScreenLoaderService, SearchByPropertyPipe, SeoService, ShowOnDirtyErrorStateMatcher, SoundEffectDirective, TextareaAutoSize, ThemeManagerService, arrayShallowEquals, defaultRippleAnimationConfig, getActualTarget, injectElement, isElement, provideNgsTheme, px, typedFromEvent, zonefreeScheduler };
1996
+ export { AUTOFOCUSABLE, AnalyticsService, AutoFocusDirective, DebounceTimeDirective, ENVIRONMENT, EnvironmentService, ErrorStateMatcher, FilterByPropertyPipe, FocusElementDirective, FormatFileSizePipe, GlobalStore, InactivityTrackerService, InitialsPipe, MutationObserverService, NGS_GENERATED_THEME_PROPERTY_NAMES, NGS_THEME_OPTIONS, OrderByPipe, PageTitleStrategyService, RIPPLE_GLOBAL_OPTIONS, ResizeObserverService, Ripple, RippleRef, RippleRenderer, RippleState, SafeHtmlPipe, SafeResourceUrlPipe, ScreenLoaderService, SearchByPropertyPipe, SeoService, ShowOnDirtyErrorStateMatcher, SoundEffectDirective, TextareaAutoSize, ThemeManagerService, arrayShallowEquals, defaultRippleAnimationConfig, generateNgsThemeCssText, generateNgsThemeProperties, getActualTarget, injectElement, isElement, provideNgsTheme, px, typedFromEvent, zonefreeScheduler };
1435
1997
  //# sourceMappingURL=ngstarter-ui-components-core.mjs.map