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.
Files changed (40) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/src/assets/css/main.css +1 -1
  3. package/dist/src/assets/css/tokens/dark.css +2 -0
  4. package/dist/src/assets/css/tokens/light.css +1 -0
  5. package/dist/src/assets/scss/tokens/_dark.scss +2 -0
  6. package/dist/src/assets/scss/tokens/_light.scss +1 -0
  7. package/dist/src/components/Btn/OrigamBtn.vue +53 -14
  8. package/dist/src/components/Chart/OrigamChartCartesian.vue +1 -1
  9. package/dist/src/components/Chart/OrigamChartPolar.vue +1 -1
  10. package/dist/src/components/Chip/OrigamChip.vue +1 -1
  11. package/dist/src/components/Code/OrigamCode.vue +0 -2
  12. package/dist/src/composables/Commons/style.composable.cjs +14 -1
  13. package/dist/src/composables/Commons/style.composable.d.ts +0 -14
  14. package/dist/src/composables/Commons/style.composable.js +13 -2
  15. package/dist/src/composables/Commons/styleTag.composable.cjs +10 -4
  16. package/dist/src/composables/Commons/styleTag.composable.js +11 -5
  17. package/dist/src/consts/Commons/ssr-style.const.cjs +8 -0
  18. package/dist/src/consts/Commons/ssr-style.const.d.ts +19 -0
  19. package/dist/src/consts/Commons/ssr-style.const.js +2 -0
  20. package/dist/src/consts/index.cjs +11 -0
  21. package/dist/src/consts/index.d.ts +1 -0
  22. package/dist/src/consts/index.js +1 -0
  23. package/dist/src/directives/Contrast/contrast.directive.cjs +58 -6
  24. package/dist/src/directives/Contrast/contrast.directive.d.ts +10 -0
  25. package/dist/src/directives/Contrast/contrast.directive.js +61 -9
  26. package/dist/src/interfaces/Btn/btn.interface.d.ts +1 -0
  27. package/dist/src/interfaces/Commons/commons.interface.d.ts +14 -0
  28. package/dist/src/interfaces/Commons/style.interface.d.ts +21 -0
  29. package/dist/src/nuxt/plugin.server.cjs +18 -0
  30. package/dist/src/nuxt/plugin.server.js +9 -0
  31. package/dist/src/origam.cjs +3 -0
  32. package/dist/src/origam.js +5 -1
  33. package/dist/src/types/tokens.type.d.ts +1 -1
  34. package/dist/src/utils/Commons/ssr-styles.util.cjs +41 -0
  35. package/dist/src/utils/Commons/ssr-styles.util.d.ts +6 -0
  36. package/dist/src/utils/Commons/ssr-styles.util.js +26 -0
  37. package/dist/src/utils/index.cjs +11 -0
  38. package/dist/src/utils/index.d.ts +1 -0
  39. package/dist/src/utils/index.js +1 -0
  40. 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
- console.warn(
124
- `[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 }).`,
125
- el
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(() => enforceContrast(el, enabled));
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
  }
@@ -33,6 +33,7 @@ export interface IBtnProps extends ICommonsComponentProps, IColorProps, IBgColor
33
33
  block?: boolean;
34
34
  slim?: boolean;
35
35
  stacked?: boolean;
36
+ wrap?: boolean;
36
37
  text?: string;
37
38
  status?: TStatus;
38
39
  statusIconPosition?: TStatusPosition;
@@ -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: {
@@ -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) {
@@ -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) {