@richardmcquiston01/dashboard-widgets-toolkit 0.11.2 → 0.13.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/dist/core.cjs +251 -0
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +57 -3
- package/dist/core.d.ts +57 -3
- package/dist/core.js +250 -1
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +251 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +250 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +109 -106
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +8 -2
- package/dist/react.d.ts +8 -2
- package/dist/react.js +109 -106
- package/dist/react.js.map +1 -1
- package/dist/{storage-VaaysVnZ.d.cts → storage-DNB7gjvT.d.cts} +1 -1
- package/dist/{storage-VaaysVnZ.d.ts → storage-DNB7gjvT.d.ts} +1 -1
- package/dist/styles.css +11 -6
- package/package.json +1 -1
package/dist/core.cjs
CHANGED
|
@@ -3236,6 +3236,255 @@ function createLayoutPersistence(adapter, options = {}) {
|
|
|
3236
3236
|
};
|
|
3237
3237
|
}
|
|
3238
3238
|
|
|
3239
|
+
// src/core/theme.ts
|
|
3240
|
+
var THEME_TOKEN_VARIABLES = {
|
|
3241
|
+
font: "--dwt-font",
|
|
3242
|
+
surface: "--dwt-surface",
|
|
3243
|
+
page: "--dwt-page",
|
|
3244
|
+
text: "--dwt-text",
|
|
3245
|
+
textSecondary: "--dwt-text-secondary",
|
|
3246
|
+
textMuted: "--dwt-text-muted",
|
|
3247
|
+
border: "--dwt-border",
|
|
3248
|
+
grid: "--dwt-grid",
|
|
3249
|
+
baseline: "--dwt-baseline",
|
|
3250
|
+
crosshair: "--dwt-crosshair",
|
|
3251
|
+
link: "--dwt-link",
|
|
3252
|
+
focus: "--dwt-focus",
|
|
3253
|
+
good: "--dwt-good",
|
|
3254
|
+
bad: "--dwt-bad",
|
|
3255
|
+
meterTrack: "--dwt-meter-track",
|
|
3256
|
+
barTrack: "--dwt-bar-track",
|
|
3257
|
+
buttonHover: "--dwt-button-hover",
|
|
3258
|
+
radius: "--dwt-radius",
|
|
3259
|
+
gap: "--dwt-gap",
|
|
3260
|
+
padding: "--dwt-padding",
|
|
3261
|
+
minColumn: "--dwt-min-column"
|
|
3262
|
+
};
|
|
3263
|
+
var LENGTH_KEYS = /* @__PURE__ */ new Set([
|
|
3264
|
+
"radius",
|
|
3265
|
+
"gap",
|
|
3266
|
+
"padding",
|
|
3267
|
+
"minColumn"
|
|
3268
|
+
]);
|
|
3269
|
+
function kindOf(key) {
|
|
3270
|
+
if (key === "font") {
|
|
3271
|
+
return "font";
|
|
3272
|
+
}
|
|
3273
|
+
return LENGTH_KEYS.has(key) ? "length" : "color";
|
|
3274
|
+
}
|
|
3275
|
+
var NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
3276
|
+
var SCOPE_PATTERN = /^[A-Za-z0-9_\-[\]=.# '"]+$/;
|
|
3277
|
+
var HEX_COLOR = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
3278
|
+
var COLOR_FUNCTION = /^(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color|color-mix|light-dark)\(.+\)$/i;
|
|
3279
|
+
var VAR_REFERENCE = /^var\(\s*--[A-Za-z0-9_-]+\s*(?:,.+)?\)$/;
|
|
3280
|
+
var COLOR_KEYWORD = /^[A-Za-z]+$/;
|
|
3281
|
+
var LENGTH_VALUE = /^(?:0|-?(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|ch|vw|vh|cqw|cqh))$/;
|
|
3282
|
+
var LENGTH_FUNCTION = /^(?:calc|min|max|clamp)\(.+\)$/i;
|
|
3283
|
+
var FONT_VALUE = /^[A-Za-z0-9 ,'"_-]+$/;
|
|
3284
|
+
function unsafeReason(value) {
|
|
3285
|
+
if ([...value].some(
|
|
3286
|
+
(character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127
|
|
3287
|
+
)) {
|
|
3288
|
+
return "contains a control character or line break";
|
|
3289
|
+
}
|
|
3290
|
+
if (/[;{}<>\\@]/.test(value)) {
|
|
3291
|
+
return "contains one of ; { } < > \\ @";
|
|
3292
|
+
}
|
|
3293
|
+
const lower = value.toLowerCase();
|
|
3294
|
+
if (lower.includes("/*") || lower.includes("*/")) {
|
|
3295
|
+
return "contains a comment marker";
|
|
3296
|
+
}
|
|
3297
|
+
if (lower.includes("url(") || lower.includes("expression(")) {
|
|
3298
|
+
return "contains url( or expression(";
|
|
3299
|
+
}
|
|
3300
|
+
let depth = 0;
|
|
3301
|
+
for (const character of value) {
|
|
3302
|
+
if (character === "(") {
|
|
3303
|
+
depth += 1;
|
|
3304
|
+
} else if (character === ")") {
|
|
3305
|
+
depth -= 1;
|
|
3306
|
+
if (depth < 0) {
|
|
3307
|
+
return "has unbalanced parentheses";
|
|
3308
|
+
}
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3311
|
+
return depth === 0 ? null : "has unbalanced parentheses";
|
|
3312
|
+
}
|
|
3313
|
+
function countOf(value, character) {
|
|
3314
|
+
return value.split(character).length - 1;
|
|
3315
|
+
}
|
|
3316
|
+
function invalidReason(kind, value) {
|
|
3317
|
+
if (value !== value.trim() || value === "") {
|
|
3318
|
+
return "must not be empty or have leading or trailing spaces";
|
|
3319
|
+
}
|
|
3320
|
+
if (kind === "font") {
|
|
3321
|
+
if (!FONT_VALUE.test(value)) {
|
|
3322
|
+
return "allows only letters, digits, spaces, commas, hyphens, underscores and quotes";
|
|
3323
|
+
}
|
|
3324
|
+
if (countOf(value, "'") % 2 !== 0 || countOf(value, '"') % 2 !== 0) {
|
|
3325
|
+
return "has an unclosed quote";
|
|
3326
|
+
}
|
|
3327
|
+
return null;
|
|
3328
|
+
}
|
|
3329
|
+
const unsafe = unsafeReason(value);
|
|
3330
|
+
if (unsafe !== null) {
|
|
3331
|
+
return unsafe;
|
|
3332
|
+
}
|
|
3333
|
+
if (value.includes("'") || value.includes('"')) {
|
|
3334
|
+
return "must not contain quotes";
|
|
3335
|
+
}
|
|
3336
|
+
if (kind === "color") {
|
|
3337
|
+
const valid2 = HEX_COLOR.test(value) || COLOR_FUNCTION.test(value) || VAR_REFERENCE.test(value) || COLOR_KEYWORD.test(value);
|
|
3338
|
+
return valid2 ? null : "is not a color (use #hex, rgb(), hsl(), oklch() and similar, var(--name) or a keyword)";
|
|
3339
|
+
}
|
|
3340
|
+
const valid = LENGTH_VALUE.test(value) || LENGTH_FUNCTION.test(value) || VAR_REFERENCE.test(value);
|
|
3341
|
+
return valid ? null : "is not a length (use a number with px, rem, em, %, ch, vw or vh, 0, calc(), min(), max(), clamp() or var(--name))";
|
|
3342
|
+
}
|
|
3343
|
+
function collectVariables(themeName, mode, tokens) {
|
|
3344
|
+
const variables = {};
|
|
3345
|
+
if (tokens === void 0) {
|
|
3346
|
+
return ok(variables);
|
|
3347
|
+
}
|
|
3348
|
+
const label = (key) => `createTheme "${themeName}": ${mode}.${key}`;
|
|
3349
|
+
const knownKeys = [
|
|
3350
|
+
...Object.keys(THEME_TOKEN_VARIABLES),
|
|
3351
|
+
"series"
|
|
3352
|
+
];
|
|
3353
|
+
for (const key of Object.keys(tokens)) {
|
|
3354
|
+
if (!knownKeys.includes(key)) {
|
|
3355
|
+
return err(
|
|
3356
|
+
`${label(key)} is not a theme token. Known tokens: ${knownKeys.join(", ")}.`
|
|
3357
|
+
);
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
for (const key of Object.keys(THEME_TOKEN_VARIABLES)) {
|
|
3361
|
+
const value = tokens[key];
|
|
3362
|
+
if (value === void 0) {
|
|
3363
|
+
continue;
|
|
3364
|
+
}
|
|
3365
|
+
if (typeof value !== "string") {
|
|
3366
|
+
return err(`${label(key)} must be a string, got ${typeof value}.`);
|
|
3367
|
+
}
|
|
3368
|
+
const reason = invalidReason(kindOf(key), value);
|
|
3369
|
+
if (reason !== null) {
|
|
3370
|
+
return err(`${label(key)} "${value}" ${reason}.`);
|
|
3371
|
+
}
|
|
3372
|
+
variables[THEME_TOKEN_VARIABLES[key]] = value;
|
|
3373
|
+
}
|
|
3374
|
+
const series = tokens.series;
|
|
3375
|
+
if (series !== void 0) {
|
|
3376
|
+
if (!Array.isArray(series) || series.length === 0) {
|
|
3377
|
+
return err(`${label("series")} must be a non-empty array of colors.`);
|
|
3378
|
+
}
|
|
3379
|
+
if (series.length > MAX_GRAPH_SERIES) {
|
|
3380
|
+
return err(
|
|
3381
|
+
`${label("series")} has ${series.length} colors; charts draw at most ${MAX_GRAPH_SERIES} series.`
|
|
3382
|
+
);
|
|
3383
|
+
}
|
|
3384
|
+
for (const [index, value] of series.entries()) {
|
|
3385
|
+
const reason = typeof value === "string" ? invalidReason("color", value) : "must be a string";
|
|
3386
|
+
if (reason !== null) {
|
|
3387
|
+
return err(
|
|
3388
|
+
`${label(`series[${index}]`)} "${String(value)}" ${reason}.`
|
|
3389
|
+
);
|
|
3390
|
+
}
|
|
3391
|
+
variables[`--dwt-series-${index + 1}`] = value;
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
return ok(variables);
|
|
3395
|
+
}
|
|
3396
|
+
function declarations(variables) {
|
|
3397
|
+
return Object.entries(variables).map(([variable, value]) => ` ${variable}: ${value};`).join("\n");
|
|
3398
|
+
}
|
|
3399
|
+
function targets(prefix, scope) {
|
|
3400
|
+
const lead = prefix === "" ? "" : `${prefix} `;
|
|
3401
|
+
return `${lead}${scope} .dwt-dashboard,
|
|
3402
|
+
${lead}${scope} .dwt-card`;
|
|
3403
|
+
}
|
|
3404
|
+
function rule(prefix, scope, variables) {
|
|
3405
|
+
return `${targets(prefix, scope)} {
|
|
3406
|
+
${declarations(variables)}
|
|
3407
|
+
}`;
|
|
3408
|
+
}
|
|
3409
|
+
function createTheme(options) {
|
|
3410
|
+
const name = options.name;
|
|
3411
|
+
if (typeof name !== "string" || !NAME_PATTERN.test(name)) {
|
|
3412
|
+
return err(
|
|
3413
|
+
`createTheme: name "${String(name)}" must start with a lower-case letter and contain only lower-case letters, digits and hyphens.`
|
|
3414
|
+
);
|
|
3415
|
+
}
|
|
3416
|
+
const scope = (options.scope ?? `[data-dwt-theme='${name}']`).trim();
|
|
3417
|
+
if (scope === "" || !SCOPE_PATTERN.test(scope)) {
|
|
3418
|
+
return err(
|
|
3419
|
+
`createTheme "${name}": scope "${scope}" must be a selector of letters, digits and _ - [ ] = . # ' " or spaces (no commas, colons or combinators).`
|
|
3420
|
+
);
|
|
3421
|
+
}
|
|
3422
|
+
const modes = ["base", "light", "dark"];
|
|
3423
|
+
const variables = {
|
|
3424
|
+
base: {},
|
|
3425
|
+
light: {},
|
|
3426
|
+
dark: {}
|
|
3427
|
+
};
|
|
3428
|
+
for (const mode of modes) {
|
|
3429
|
+
const collected = collectVariables(
|
|
3430
|
+
name,
|
|
3431
|
+
mode,
|
|
3432
|
+
options[mode]
|
|
3433
|
+
);
|
|
3434
|
+
if (!collected.ok) {
|
|
3435
|
+
return collected;
|
|
3436
|
+
}
|
|
3437
|
+
variables[mode] = collected.value;
|
|
3438
|
+
}
|
|
3439
|
+
if (modes.every((mode) => Object.keys(variables[mode]).length === 0)) {
|
|
3440
|
+
return err(
|
|
3441
|
+
`createTheme "${name}": no tokens were set. Pass at least one value in base, light or dark.`
|
|
3442
|
+
);
|
|
3443
|
+
}
|
|
3444
|
+
const blocks = [];
|
|
3445
|
+
if (Object.keys(variables.base).length > 0) {
|
|
3446
|
+
blocks.push(rule("", scope, variables.base));
|
|
3447
|
+
}
|
|
3448
|
+
if (Object.keys(variables.light).length > 0) {
|
|
3449
|
+
blocks.push(
|
|
3450
|
+
rule(":root:where([data-theme='light'])", scope, variables.light)
|
|
3451
|
+
);
|
|
3452
|
+
blocks.push(
|
|
3453
|
+
`@media (prefers-color-scheme: light) {
|
|
3454
|
+
${indent(
|
|
3455
|
+
rule(
|
|
3456
|
+
":root:where(:not([data-theme='dark'], .dark))",
|
|
3457
|
+
scope,
|
|
3458
|
+
variables.light
|
|
3459
|
+
)
|
|
3460
|
+
)}
|
|
3461
|
+
}`
|
|
3462
|
+
);
|
|
3463
|
+
}
|
|
3464
|
+
if (Object.keys(variables.dark).length > 0) {
|
|
3465
|
+
blocks.push(
|
|
3466
|
+
rule(":root:where([data-theme='dark'], .dark)", scope, variables.dark)
|
|
3467
|
+
);
|
|
3468
|
+
blocks.push(
|
|
3469
|
+
`@media (prefers-color-scheme: dark) {
|
|
3470
|
+
${indent(
|
|
3471
|
+
rule(":root:where(:not([data-theme='light']))", scope, variables.dark)
|
|
3472
|
+
)}
|
|
3473
|
+
}`
|
|
3474
|
+
);
|
|
3475
|
+
}
|
|
3476
|
+
return ok({
|
|
3477
|
+
name,
|
|
3478
|
+
scope,
|
|
3479
|
+
css: `${blocks.join("\n\n")}
|
|
3480
|
+
`,
|
|
3481
|
+
variables
|
|
3482
|
+
});
|
|
3483
|
+
}
|
|
3484
|
+
function indent(block) {
|
|
3485
|
+
return block.split("\n").map((line) => ` ${line}`).join("\n");
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3239
3488
|
exports.DATE_RANGE_PRESETS = DATE_RANGE_PRESETS;
|
|
3240
3489
|
exports.DEFAULT_COMPARISON_LABEL = DEFAULT_COMPARISON_LABEL;
|
|
3241
3490
|
exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
|
|
@@ -3258,6 +3507,7 @@ exports.MAX_WIDGET_OPTIONS = MAX_WIDGET_OPTIONS;
|
|
|
3258
3507
|
exports.MAX_WIDGET_WIDTH = MAX_WIDGET_WIDTH;
|
|
3259
3508
|
exports.MIN_WIDGET_WIDTH = MIN_WIDGET_WIDTH;
|
|
3260
3509
|
exports.OPTION_KEY_PATTERN = OPTION_KEY_PATTERN;
|
|
3510
|
+
exports.THEME_TOKEN_VARIABLES = THEME_TOKEN_VARIABLES;
|
|
3261
3511
|
exports.VALUE_FORMATS = VALUE_FORMATS;
|
|
3262
3512
|
exports.WIDGET_FILLS = WIDGET_FILLS;
|
|
3263
3513
|
exports.WIDGET_KINDS = WIDGET_KINDS;
|
|
@@ -3271,6 +3521,7 @@ exports.baseColumnSpan = baseColumnSpan;
|
|
|
3271
3521
|
exports.cacheKeyFor = cacheKeyFor;
|
|
3272
3522
|
exports.coerceOptionValue = coerceOptionValue;
|
|
3273
3523
|
exports.createLayoutPersistence = createLayoutPersistence;
|
|
3524
|
+
exports.createTheme = createTheme;
|
|
3274
3525
|
exports.createWidgetLoader = createWidgetLoader;
|
|
3275
3526
|
exports.defaultDetailQuery = defaultDetailQuery;
|
|
3276
3527
|
exports.defaultOptionValue = defaultOptionValue;
|