origam 2.27.0 → 2.29.1
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 +43 -0
- package/dist/src/assets/css/main.css +1 -1
- package/dist/src/assets/css/tokens/dark.css +2 -0
- package/dist/src/assets/css/tokens/light.css +1 -0
- package/dist/src/assets/scss/tokens/_dark.scss +2 -0
- package/dist/src/assets/scss/tokens/_light.scss +1 -0
- package/dist/src/components/Btn/OrigamBtn.vue +53 -14
- package/dist/src/components/Chart/OrigamChartCartesian.vue +1 -1
- package/dist/src/components/Chart/OrigamChartPolar.vue +1 -1
- package/dist/src/components/Chip/OrigamChip.vue +1 -1
- package/dist/src/components/Code/OrigamCode.vue +0 -2
- package/dist/src/composables/Commons/style.composable.cjs +14 -1
- package/dist/src/composables/Commons/style.composable.d.ts +0 -14
- package/dist/src/composables/Commons/style.composable.js +13 -2
- package/dist/src/composables/Commons/styleTag.composable.cjs +10 -4
- package/dist/src/composables/Commons/styleTag.composable.js +11 -5
- package/dist/src/consts/Commons/ssr-style.const.cjs +8 -0
- package/dist/src/consts/Commons/ssr-style.const.d.ts +19 -0
- package/dist/src/consts/Commons/ssr-style.const.js +2 -0
- package/dist/src/consts/index.cjs +11 -0
- package/dist/src/consts/index.d.ts +1 -0
- package/dist/src/consts/index.js +1 -0
- package/dist/src/directives/Contrast/contrast.directive.cjs +58 -6
- package/dist/src/directives/Contrast/contrast.directive.d.ts +10 -0
- package/dist/src/directives/Contrast/contrast.directive.js +61 -9
- package/dist/src/interfaces/Btn/btn.interface.d.ts +1 -0
- package/dist/src/interfaces/Commons/commons.interface.d.ts +14 -0
- package/dist/src/interfaces/Commons/style.interface.d.ts +21 -0
- package/dist/src/nuxt/plugin.server.cjs +18 -0
- package/dist/src/nuxt/plugin.server.js +9 -0
- package/dist/src/origam.cjs +3 -0
- package/dist/src/origam.js +5 -1
- package/dist/src/types/tokens.type.d.ts +1 -1
- package/dist/src/utils/Commons/ssr-styles.util.cjs +41 -0
- package/dist/src/utils/Commons/ssr-styles.util.d.ts +6 -0
- package/dist/src/utils/Commons/ssr-styles.util.js +26 -0
- package/dist/src/utils/index.cjs +11 -0
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/index.js +1 -0
- package/package.json +1 -1
|
@@ -120,15 +120,70 @@ function enforceContrast(el, enabled) {
|
|
|
120
120
|
const better = wcagRatio(WHITE, bg) >= wcagRatio(BLACK, bg) ? "#fff" : "#000";
|
|
121
121
|
el.style.setProperty("color", better, "important");
|
|
122
122
|
el.dataset.origamContrastFixed = "true";
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
if (import.meta.env?.DEV) {
|
|
124
|
+
console.warn(
|
|
125
|
+
`[origam] Low text contrast (${ratio.toFixed(2)}:1 < ${config.threshold}:1): text rgb(${fg.join(", ")}) on background rgb(${bg.join(", ")}). Overriding text colour to ${better} for legibility. Disable with createOrigam({ contrast: false }).`,
|
|
126
|
+
el
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const MAX_SETTLE_PASSES = 4;
|
|
131
|
+
const COLOR_TRANSITION_PROPERTIES = /* @__PURE__ */ new Set(["color", "background-color"]);
|
|
132
|
+
function declaredTransitionMs(el) {
|
|
133
|
+
const toMs = (value) => {
|
|
134
|
+
const n = parseFloat(value);
|
|
135
|
+
if (Number.isNaN(n)) return 0;
|
|
136
|
+
return value.trim().endsWith("ms") ? n : n * 1e3;
|
|
137
|
+
};
|
|
138
|
+
let longest = 0;
|
|
139
|
+
for (let node = el; node; node = node.parentElement) {
|
|
140
|
+
const style = getComputedStyle(node);
|
|
141
|
+
const durations = style.transitionDuration.split(",");
|
|
142
|
+
const delays = style.transitionDelay.split(",");
|
|
143
|
+
durations.forEach((duration, i) => {
|
|
144
|
+
longest = Math.max(longest, toMs(duration) + toMs(delays[i % delays.length] ?? "0"));
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return longest;
|
|
148
|
+
}
|
|
149
|
+
function runningColorTransitions(el) {
|
|
150
|
+
const found = [];
|
|
151
|
+
for (let node = el; node; node = node.parentElement) {
|
|
152
|
+
for (const animation of node.getAnimations()) {
|
|
153
|
+
const property = animation.transitionProperty;
|
|
154
|
+
if (property && COLOR_TRANSITION_PROPERTIES.has(property) && animation.playState !== "finished") {
|
|
155
|
+
found.push(animation);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return found;
|
|
160
|
+
}
|
|
161
|
+
function forceStyleRecalc(el) {
|
|
162
|
+
return getComputedStyle(el).color;
|
|
163
|
+
}
|
|
164
|
+
function settleThenEnforce(el, enabled, pending, pass = 0) {
|
|
165
|
+
if (pending.cancelled) return;
|
|
166
|
+
if (!forceStyleRecalc(el)) return;
|
|
167
|
+
if (typeof el.getAnimations === "function") {
|
|
168
|
+
const running = pass < MAX_SETTLE_PASSES ? runningColorTransitions(el) : [];
|
|
169
|
+
if (running.length) {
|
|
170
|
+
Promise.allSettled(running.map((animation) => animation.finished)).then(() => settleThenEnforce(el, enabled, pending, pass + 1));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
enforceContrast(el, enabled);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const wait = declaredTransitionMs(el);
|
|
177
|
+
if (wait > 0 && pass === 0 && typeof setTimeout !== "undefined") {
|
|
178
|
+
pending.timeout = setTimeout(() => settleThenEnforce(el, enabled, pending, 1), wait);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
enforceContrast(el, enabled);
|
|
127
182
|
}
|
|
128
|
-
const SETTLE_MS = 250;
|
|
129
183
|
function cancelScheduled(el) {
|
|
130
184
|
const pending = el._contrastTimers;
|
|
131
185
|
if (!pending) return;
|
|
186
|
+
pending.cancelled = true;
|
|
132
187
|
if (pending.raf !== void 0 && typeof cancelAnimationFrame !== "undefined") {
|
|
133
188
|
cancelAnimationFrame(pending.raf);
|
|
134
189
|
}
|
|
@@ -141,10 +196,7 @@ function schedule(el, enabled) {
|
|
|
141
196
|
cancelScheduled(el);
|
|
142
197
|
const pending = {};
|
|
143
198
|
if (typeof requestAnimationFrame !== "undefined") {
|
|
144
|
-
pending.raf = requestAnimationFrame(() =>
|
|
145
|
-
}
|
|
146
|
-
if (typeof setTimeout !== "undefined") {
|
|
147
|
-
pending.timeout = setTimeout(() => enforceContrast(el, enabled), SETTLE_MS);
|
|
199
|
+
pending.raf = requestAnimationFrame(() => settleThenEnforce(el, enabled, pending));
|
|
148
200
|
}
|
|
149
201
|
el._contrastTimers = pending;
|
|
150
202
|
}
|
|
@@ -15,6 +15,20 @@ import { TSSROptions } from '../../types/Commons/display.type';
|
|
|
15
15
|
* `enabled` toggles the whole feature; `threshold` is the minimum acceptable
|
|
16
16
|
* WCAG contrast ratio (default 4.5:1 — AA for normal text).
|
|
17
17
|
*/
|
|
18
|
+
/*********************************************************
|
|
19
|
+
* IContrastScheduled
|
|
20
|
+
*
|
|
21
|
+
* @description
|
|
22
|
+
* What `v-contrast` has queued for one element: the animation frame that
|
|
23
|
+
* starts the measure, the fallback timer (browsers without `getAnimations`,
|
|
24
|
+
* derived from the declared transition) and a flag that cancels a measure
|
|
25
|
+
* already waiting on a transition. Stored on the element as `_contrastTimers`.
|
|
26
|
+
********************************************************/
|
|
27
|
+
export interface IContrastScheduled {
|
|
28
|
+
raf?: number;
|
|
29
|
+
timeout?: number;
|
|
30
|
+
cancelled?: boolean;
|
|
31
|
+
}
|
|
18
32
|
export interface IContrastOptions {
|
|
19
33
|
enabled?: boolean;
|
|
20
34
|
threshold?: number;
|
|
@@ -23,3 +23,24 @@ export interface IStyleTagOptions extends IConfigurableDocument {
|
|
|
23
23
|
*/
|
|
24
24
|
id?: string;
|
|
25
25
|
}
|
|
26
|
+
/*********************************************************
|
|
27
|
+
* ISsrStyleEntry / ISsrStyleCollector (#1092)
|
|
28
|
+
*
|
|
29
|
+
* @description
|
|
30
|
+
* `ISsrStyleEntry` is one `useStyle()` rule resolved for the server render:
|
|
31
|
+
* `id` is the DOM id of the `<style>` tag it belongs to, `css` the
|
|
32
|
+
* `#element-id { … }` rule, already safe to embed in a `<style>`.
|
|
33
|
+
*
|
|
34
|
+
* @description
|
|
35
|
+
* `ISsrStyleCollector` is the per-app registry of those rules. Rules are
|
|
36
|
+
* registered as GETTERS and read at collection time, so a value a later pass
|
|
37
|
+
* of the render settled on is what ships.
|
|
38
|
+
********************************************************/
|
|
39
|
+
export interface ISsrStyleEntry {
|
|
40
|
+
id: string;
|
|
41
|
+
css: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ISsrStyleCollector {
|
|
44
|
+
add(id: string, css: () => string): void;
|
|
45
|
+
entries(): ISsrStyleEntry[];
|
|
46
|
+
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
|
|
7
7
|
var _origam = require("../origam.cjs");
|
|
8
8
|
var _applyTheme = require("../utils/Commons/apply-theme.util.cjs");
|
|
9
|
+
var _ssrStyles = require("../utils/Commons/ssr-styles.util.cjs");
|
|
9
10
|
var _theme = require("../consts/Commons/theme.const.cjs");
|
|
10
11
|
var _app = require("#app");
|
|
11
12
|
function resolveServerTheme(cookieValue, config) {
|
|
@@ -79,6 +80,23 @@ module.exports = (0, _app.defineNuxtPlugin)({
|
|
|
79
80
|
});
|
|
80
81
|
origam._defaultsRef.value = origam._activeDefaultsFor(resolvedTheme === _theme.ORIGAM_THEME_AUTO ? "" : resolvedTheme, resolvedMode);
|
|
81
82
|
nuxtApp.vueApp.use(origam);
|
|
83
|
+
nuxtApp.hook("app:rendered", ({
|
|
84
|
+
ssrContext
|
|
85
|
+
}) => {
|
|
86
|
+
const styles = (0, _ssrStyles.getSsrStyles)(nuxtApp.vueApp);
|
|
87
|
+
if (styles.length && ssrContext) {
|
|
88
|
+
ssrContext.head.push({
|
|
89
|
+
style: styles.map(({
|
|
90
|
+
id,
|
|
91
|
+
css
|
|
92
|
+
}) => ({
|
|
93
|
+
id,
|
|
94
|
+
key: id,
|
|
95
|
+
innerHTML: css
|
|
96
|
+
}))
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
82
100
|
return {
|
|
83
101
|
provide: {
|
|
84
102
|
origam: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createOrigam } from "../origam.js";
|
|
2
2
|
import { themeToCss } from "../utils/Commons/apply-theme.util.js";
|
|
3
|
+
import { getSsrStyles } from "../utils/Commons/ssr-styles.util.js";
|
|
3
4
|
import { ORIGAM_MODE_ATTR, ORIGAM_MODE_DARK, ORIGAM_MODE_LIGHT, ORIGAM_THEME_ATTR, ORIGAM_THEME_AUTO } from "../consts/Commons/theme.const.js";
|
|
4
5
|
import { defineNuxtPlugin, useCookie, useHead, useRequestHeaders, useRuntimeConfig } from "#app";
|
|
5
6
|
function resolveServerTheme(cookieValue, config) {
|
|
@@ -69,6 +70,14 @@ export default defineNuxtPlugin({
|
|
|
69
70
|
resolvedMode
|
|
70
71
|
);
|
|
71
72
|
nuxtApp.vueApp.use(origam);
|
|
73
|
+
nuxtApp.hook("app:rendered", ({ ssrContext }) => {
|
|
74
|
+
const styles = getSsrStyles(nuxtApp.vueApp);
|
|
75
|
+
if (styles.length && ssrContext) {
|
|
76
|
+
ssrContext.head.push({
|
|
77
|
+
style: styles.map(({ id, css }) => ({ id, key: id, innerHTML: css }))
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
72
81
|
return {
|
|
73
82
|
provide: {
|
|
74
83
|
origam: {
|
package/dist/src/origam.cjs
CHANGED
|
@@ -69,6 +69,9 @@ function createOrigam(origam = {}) {
|
|
|
69
69
|
app.provide(_consts.ORIGAM_GO_TO_KEY, goTo);
|
|
70
70
|
app.provide(_consts.ORIGAM_THEMES_KEY, installedThemes);
|
|
71
71
|
app.provide(_consts.ORIGAM_DEFAULTS_KEY, defaultsRef);
|
|
72
|
+
if (!_consts.IN_BROWSER) {
|
|
73
|
+
app.provide(_consts.ORIGAM_SSR_STYLES_KEY, (0, _utils.registerSsrStyleCollector)(app));
|
|
74
|
+
}
|
|
72
75
|
(0, _composables.installThemePropsResolver)(app, themedKeysUnion, variantPresets);
|
|
73
76
|
app.provide(_consts.ORIGAM_THEME_DEFAULTS_KEY, (brand, mode) => activeDefaultsFor(allThemes, brand, mode));
|
|
74
77
|
if (_consts.IN_BROWSER && options.ssr) {
|
package/dist/src/origam.js
CHANGED
|
@@ -20,13 +20,14 @@ import {
|
|
|
20
20
|
ORIGAM_GO_TO_KEY,
|
|
21
21
|
ORIGAM_ICONS_KEY,
|
|
22
22
|
ORIGAM_LOCALE_KEY,
|
|
23
|
+
ORIGAM_SSR_STYLES_KEY,
|
|
23
24
|
ORIGAM_THEME_DEFAULTS_KEY,
|
|
24
25
|
ORIGAM_THEMES_KEY,
|
|
25
26
|
VARIANT_PRESETS
|
|
26
27
|
} from "./consts/index.js";
|
|
27
28
|
import * as origamDirectives from "./directives/index.js";
|
|
28
29
|
import { setContrastConfig } from "./directives/Contrast/contrast.directive.js";
|
|
29
|
-
import { applyThemes, installedThemesFromList, mergeDeep } from "./utils/index.js";
|
|
30
|
+
import { applyThemes, installedThemesFromList, mergeDeep, registerSsrStyleCollector } from "./utils/index.js";
|
|
30
31
|
import "@mdi/font/css/materialdesignicons.css";
|
|
31
32
|
import { defineComponent, effectScope, nextTick, reactive } from "vue";
|
|
32
33
|
export function createOrigam(origam = {}) {
|
|
@@ -88,6 +89,9 @@ export function createOrigam(origam = {}) {
|
|
|
88
89
|
app.provide(ORIGAM_GO_TO_KEY, goTo);
|
|
89
90
|
app.provide(ORIGAM_THEMES_KEY, installedThemes);
|
|
90
91
|
app.provide(ORIGAM_DEFAULTS_KEY, defaultsRef);
|
|
92
|
+
if (!IN_BROWSER) {
|
|
93
|
+
app.provide(ORIGAM_SSR_STYLES_KEY, registerSsrStyleCollector(app));
|
|
94
|
+
}
|
|
91
95
|
installThemePropsResolver(app, themedKeysUnion, variantPresets);
|
|
92
96
|
app.provide(ORIGAM_THEME_DEFAULTS_KEY, (brand, mode) => activeDefaultsFor(allThemes, brand, mode));
|
|
93
97
|
if (IN_BROWSER && options.ssr) {
|