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
|
@@ -319,6 +319,7 @@
|
|
|
319
319
|
--origam-btn---padding-md: var(--origam-space---4);
|
|
320
320
|
--origam-btn---padding-lg: var(--origam-space---5);
|
|
321
321
|
--origam-btn---padding-xl: var(--origam-space---6);
|
|
322
|
+
--origam-btn---padding-block: 0px;
|
|
322
323
|
--origam-btn---font-size: var(--origam-font__size---md);
|
|
323
324
|
--origam-btn---font-weight: var(--origam-font__weight---medium);
|
|
324
325
|
--origam-btn---letter-spacing: var(--origam-font__letterSpacing---widest);
|
|
@@ -3332,6 +3333,7 @@
|
|
|
3332
3333
|
--origam-btn---padding-md: var(--origam-space---4);
|
|
3333
3334
|
--origam-btn---padding-lg: var(--origam-space---5);
|
|
3334
3335
|
--origam-btn---padding-xl: var(--origam-space---6);
|
|
3336
|
+
--origam-btn---padding-block: 0px;
|
|
3335
3337
|
--origam-btn---font-size: var(--origam-font__size---md);
|
|
3336
3338
|
--origam-btn---font-weight: var(--origam-font__weight---medium);
|
|
3337
3339
|
--origam-btn---letter-spacing: var(--origam-font__letterSpacing---widest);
|
|
@@ -219,6 +219,7 @@
|
|
|
219
219
|
--origam-btn---padding-md: var(--origam-space---4);
|
|
220
220
|
--origam-btn---padding-lg: var(--origam-space---5);
|
|
221
221
|
--origam-btn---padding-xl: var(--origam-space---6);
|
|
222
|
+
--origam-btn---padding-block: 0px;
|
|
222
223
|
--origam-btn---font-size: var(--origam-font__size---md);
|
|
223
224
|
--origam-btn---font-weight: var(--origam-font__weight---medium);
|
|
224
225
|
--origam-btn---letter-spacing: var(--origam-font__letterSpacing---widest);
|
|
@@ -319,6 +319,7 @@
|
|
|
319
319
|
--origam-btn---padding-md: var(--origam-space---4);
|
|
320
320
|
--origam-btn---padding-lg: var(--origam-space---5);
|
|
321
321
|
--origam-btn---padding-xl: var(--origam-space---6);
|
|
322
|
+
--origam-btn---padding-block: 0px;
|
|
322
323
|
--origam-btn---font-size: var(--origam-font__size---md);
|
|
323
324
|
--origam-btn---font-weight: var(--origam-font__weight---medium);
|
|
324
325
|
--origam-btn---letter-spacing: var(--origam-font__letterSpacing---widest);
|
|
@@ -3332,6 +3333,7 @@
|
|
|
3332
3333
|
--origam-btn---padding-md: var(--origam-space---4);
|
|
3333
3334
|
--origam-btn---padding-lg: var(--origam-space---5);
|
|
3334
3335
|
--origam-btn---padding-xl: var(--origam-space---6);
|
|
3336
|
+
--origam-btn---padding-block: 0px;
|
|
3335
3337
|
--origam-btn---font-size: var(--origam-font__size---md);
|
|
3336
3338
|
--origam-btn---font-weight: var(--origam-font__weight---medium);
|
|
3337
3339
|
--origam-btn---letter-spacing: var(--origam-font__letterSpacing---widest);
|
|
@@ -219,6 +219,7 @@
|
|
|
219
219
|
--origam-btn---padding-md: var(--origam-space---4);
|
|
220
220
|
--origam-btn---padding-lg: var(--origam-space---5);
|
|
221
221
|
--origam-btn---padding-xl: var(--origam-space---6);
|
|
222
|
+
--origam-btn---padding-block: 0px;
|
|
222
223
|
--origam-btn---font-size: var(--origam-font__size---md);
|
|
223
224
|
--origam-btn---font-weight: var(--origam-font__weight---medium);
|
|
224
225
|
--origam-btn---letter-spacing: var(--origam-font__letterSpacing---widest);
|
|
@@ -145,6 +145,7 @@ const props = defineProps({
|
|
|
145
145
|
block: { type: Boolean, required: false },
|
|
146
146
|
slim: { type: Boolean, required: false },
|
|
147
147
|
stacked: { type: Boolean, required: false },
|
|
148
|
+
wrap: { type: Boolean, required: false },
|
|
148
149
|
text: { type: String, required: false },
|
|
149
150
|
status: { type: null, required: false },
|
|
150
151
|
statusIconPosition: { type: null, required: false },
|
|
@@ -396,7 +397,8 @@ const btnClasses = computed(() => {
|
|
|
396
397
|
// which stays in the DOM (width and name preserved).
|
|
397
398
|
[`origam-btn--loader-${loaderKind.value}`]: isLoading.value,
|
|
398
399
|
"origam-btn--slim": props.slim,
|
|
399
|
-
"origam-btn--stacked": props.stacked
|
|
400
|
+
"origam-btn--stacked": props.stacked,
|
|
401
|
+
"origam-btn--wrap": props.wrap
|
|
400
402
|
},
|
|
401
403
|
variantClasses.value,
|
|
402
404
|
borderClasses.value,
|
|
@@ -459,6 +461,10 @@ defineExpose({
|
|
|
459
461
|
// blockifies to `block`, i.e. byte-for-byte today's computed value, so
|
|
460
462
|
// no existing layout moves. `&--block` still overrides it with `flex`.
|
|
461
463
|
display: inline-block;
|
|
464
|
+
// #1094 — inoperant tant que la racine est `inline-block` ; prend effet
|
|
465
|
+
// sur `&--block` (`display: flex`), ou `height: auto` + `min-height`
|
|
466
|
+
// laisseraient sinon le contenu colle en haut.
|
|
467
|
+
align-items: center;
|
|
462
468
|
|
|
463
469
|
position: var(--origam-btn---position, relative);
|
|
464
470
|
vertical-align: middle;
|
|
@@ -475,12 +481,22 @@ defineExpose({
|
|
|
475
481
|
transition-duration: var(--origam-btn---transition-duration, 0.28s);
|
|
476
482
|
transition-timing-function: var(--origam-btn---transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
477
483
|
|
|
478
|
-
padding
|
|
484
|
+
// ⛔ #929 — le padding vertical est LU depuis `--origam-btn---padding-block`
|
|
485
|
+
// (repli `0` : un bouton qui ne le pose pas ne bouge pas). Il n'etait
|
|
486
|
+
// qu'ecrit, jamais lu. Les rubriques `&--size-*` / `&--slim` ne posent
|
|
487
|
+
// plus que `padding-inline`, sans quoi leur shorthand `padding: 0 …`
|
|
488
|
+
// remettrait ce bloc a zero.
|
|
489
|
+
padding-block: var(--origam-btn---padding-block, 0);
|
|
490
|
+
padding-inline: calc(16px + var(--origam-btn---density-padding-x, 0px));
|
|
479
491
|
|
|
480
492
|
width: var(--origam-btn---width, auto);
|
|
481
493
|
min-width: calc(var(--origam-btn---min-width, 64px) + var(--origam-btn---density, 0px));
|
|
482
494
|
max-width: var(--origam-btn---max-width, 100%);
|
|
483
|
-
|
|
495
|
+
// ⛔ #1094 — la hauteur est un MINIMUM, plus une valeur fixe : `height: auto`
|
|
496
|
+
// laisse un contenu a deux lignes (`wrap`) agrandir le bouton, et le
|
|
497
|
+
// `min-height` ci-dessous garde la taille du token pour un contenu d'une
|
|
498
|
+
// ligne. La prop `height` reste prioritaire (declaration inline).
|
|
499
|
+
height: auto;
|
|
484
500
|
// ⛔ C2 (#597) — `--origam-btn---min-height` reste NON DECLARE, a dessein.
|
|
485
501
|
// Son repli est `calc(height + density)`, deux vars reglees PAR INSTANCE
|
|
486
502
|
// (`&--size-*` / `&--density-*` plus bas dans ce bloc). Une custom property
|
|
@@ -488,6 +504,13 @@ defineExpose({
|
|
|
488
504
|
// figerait la hauteur minimale a la taille/densite racine et les props
|
|
489
505
|
// `size` / `density` cesseraient d'agir sur elle. Faux positif de la garde,
|
|
490
506
|
// qui compare des noms et non des chaines de repli.
|
|
507
|
+
//
|
|
508
|
+
// ⛔ #1094 — ce `min-height` est desormais le SEUL garant de la hauteur au repos
|
|
509
|
+
// (la hauteur est `auto`). `--origam-btn---min-height` peut le RELEVER (le site
|
|
510
|
+
// marketing le fait : 34 / 38 / 44 px) ; le poser a `0` SUPPRIME le plancher et le
|
|
511
|
+
// bouton retombe a la hauteur de son contenu. Avec une hauteur fixe, ce `0` etait
|
|
512
|
+
// sans effet : c'est pourquoi Chip / Code / graphes l'ecrivaient en pure perte, et
|
|
513
|
+
// pourquoi ces ecritures ont ete retirees dans le meme lot.
|
|
491
514
|
min-height: var(--origam-btn---min-height, calc(var(--origam-btn---height, 36px) + var(--origam-btn---density, 0px)));
|
|
492
515
|
max-height: var(--origam-btn---max-height, 100%);
|
|
493
516
|
|
|
@@ -559,7 +582,7 @@ defineExpose({
|
|
|
559
582
|
--origam-btn---height: var(--origam-btn---height-xs, 20px);
|
|
560
583
|
--origam-btn---font-size: 0.625rem;
|
|
561
584
|
--origam-btn---min-width: 36px;
|
|
562
|
-
padding:
|
|
585
|
+
padding-inline: calc(var(--origam-btn---padding-xs, 8px) + var(--origam-btn---density-padding-x, 0px));
|
|
563
586
|
|
|
564
587
|
:deep(.origam-icon) {
|
|
565
588
|
--origam-btn---font-size: 16px;
|
|
@@ -570,7 +593,7 @@ defineExpose({
|
|
|
570
593
|
--origam-btn---height: var(--origam-btn---height-sm, 28px);
|
|
571
594
|
--origam-btn---font-size: 0.75rem;
|
|
572
595
|
--origam-btn---min-width: 50px;
|
|
573
|
-
padding:
|
|
596
|
+
padding-inline: calc(var(--origam-btn---padding-sm, 12px) + var(--origam-btn---density-padding-x, 0px));
|
|
574
597
|
|
|
575
598
|
:deep(.origam-icon) {
|
|
576
599
|
--origam-btn---font-size: 20px;
|
|
@@ -578,7 +601,7 @@ defineExpose({
|
|
|
578
601
|
}
|
|
579
602
|
|
|
580
603
|
&--size-default {
|
|
581
|
-
padding:
|
|
604
|
+
padding-inline: calc(var(--origam-btn---padding-md, 16px) + var(--origam-btn---density-padding-x, 0px));
|
|
582
605
|
|
|
583
606
|
:deep(.origam-icon) {
|
|
584
607
|
--origam-btn---font-size: 24px;
|
|
@@ -589,7 +612,7 @@ defineExpose({
|
|
|
589
612
|
--origam-btn---height: var(--origam-btn---height-lg, 44px);
|
|
590
613
|
--origam-btn---font-size: 1rem;
|
|
591
614
|
--origam-btn---min-width: 78px;
|
|
592
|
-
padding:
|
|
615
|
+
padding-inline: calc(var(--origam-btn---padding-lg, 20px) + var(--origam-btn---density-padding-x, 0px));
|
|
593
616
|
|
|
594
617
|
:deep(.origam-icon) {
|
|
595
618
|
--origam-btn---font-size: 28px;
|
|
@@ -600,7 +623,7 @@ defineExpose({
|
|
|
600
623
|
--origam-btn---height: var(--origam-btn---height-xl, 52px);
|
|
601
624
|
--origam-btn---font-size: 1.125rem;
|
|
602
625
|
--origam-btn---min-width: 92px;
|
|
603
|
-
padding:
|
|
626
|
+
padding-inline: calc(var(--origam-btn---padding-xl, 24px) + var(--origam-btn---density-padding-x, 0px));
|
|
604
627
|
|
|
605
628
|
:deep(.origam-icon) {
|
|
606
629
|
--origam-btn---font-size: 32px;
|
|
@@ -728,6 +751,11 @@ defineExpose({
|
|
|
728
751
|
--origam-btn---width: calc(var(--origam-btn---height, 36px) + var(--origam-btn---density, 0px));
|
|
729
752
|
|
|
730
753
|
padding: 0;
|
|
754
|
+
// #1094 — un bouton icone est CARRE : sa largeur derive du meme token que sa
|
|
755
|
+
// hauteur (`--origam-btn---width` ci-dessus). Aucun libelle ne peut deborder,
|
|
756
|
+
// donc la hauteur reste fixe — sans quoi un contenu plus haut que le carre
|
|
757
|
+
// (icone de Chip, `min-height: 0` des consommateurs) le deformerait.
|
|
758
|
+
height: calc(var(--origam-btn---height, 36px) + var(--origam-btn---density, 0px));
|
|
731
759
|
|
|
732
760
|
#{$this}__loader {
|
|
733
761
|
display: flex;
|
|
@@ -1016,35 +1044,35 @@ defineExpose({
|
|
|
1016
1044
|
--origam-btn---height: 56px;
|
|
1017
1045
|
font-size: 0.625rem;
|
|
1018
1046
|
min-width: 56px;
|
|
1019
|
-
padding:
|
|
1047
|
+
padding-inline: calc(12px + var(--origam-btn---density-padding-x, 0px));
|
|
1020
1048
|
}
|
|
1021
1049
|
|
|
1022
1050
|
&#{$this}--size-small {
|
|
1023
1051
|
--origam-btn---height: 64px;
|
|
1024
1052
|
font-size: 0.75rem;
|
|
1025
1053
|
min-width: 64px;
|
|
1026
|
-
padding:
|
|
1054
|
+
padding-inline: calc(14px + var(--origam-btn---density-padding-x, 0px));
|
|
1027
1055
|
}
|
|
1028
1056
|
|
|
1029
1057
|
&#{$this}--size-default {
|
|
1030
1058
|
--origam-btn---height: 72px;
|
|
1031
1059
|
font-size: 0.875rem;
|
|
1032
1060
|
min-width: 72px;
|
|
1033
|
-
padding:
|
|
1061
|
+
padding-inline: calc(16px + var(--origam-btn---density-padding-x, 0px));
|
|
1034
1062
|
}
|
|
1035
1063
|
|
|
1036
1064
|
&#{$this}--size-large {
|
|
1037
1065
|
--origam-btn---height: 80px;
|
|
1038
1066
|
font-size: 1rem;
|
|
1039
1067
|
min-width: 80px;
|
|
1040
|
-
padding:
|
|
1068
|
+
padding-inline: calc(18px + var(--origam-btn---density-padding-x, 0px));
|
|
1041
1069
|
}
|
|
1042
1070
|
|
|
1043
1071
|
&#{$this}--size-x-large {
|
|
1044
1072
|
--origam-btn---height: 88px;
|
|
1045
1073
|
font-size: 1.125rem;
|
|
1046
1074
|
min-width: 88px;
|
|
1047
|
-
padding:
|
|
1075
|
+
padding-inline: calc(20px + var(--origam-btn---density-padding-x, 0px));
|
|
1048
1076
|
}
|
|
1049
1077
|
|
|
1050
1078
|
&#{$this}--density-comfortable {
|
|
@@ -1057,7 +1085,18 @@ defineExpose({
|
|
|
1057
1085
|
}
|
|
1058
1086
|
|
|
1059
1087
|
&--slim {
|
|
1060
|
-
padding:
|
|
1088
|
+
padding-inline: 8px;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
// #1093 — le libelle reste sur UNE ligne (`__content { white-space: nowrap }`)
|
|
1092
|
+
// sauf demande : `wrap` le laisse passer a la ligne. Le bouton grandit alors
|
|
1093
|
+
// (sa hauteur est un minimum, #1094) au lieu de laisser le texte deborder.
|
|
1094
|
+
// `text-align: center` : un `<a>` / `<span>` ne centre pas ses lignes seul.
|
|
1095
|
+
&--wrap {
|
|
1096
|
+
#{$this}__content {
|
|
1097
|
+
white-space: normal;
|
|
1098
|
+
text-align: center;
|
|
1099
|
+
}
|
|
1061
1100
|
}
|
|
1062
1101
|
|
|
1063
1102
|
&--rounded {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
variant="outlined"
|
|
49
49
|
:text="drilldownBackLabel"
|
|
50
50
|
:aria-label="drilldownBackLabel"
|
|
51
|
-
:style="{ '--origam-btn---min-
|
|
51
|
+
:style="{ '--origam-btn---min-width': '0' }"
|
|
52
52
|
data-cy="origam-chart-cartesian-breadcrumb-back"
|
|
53
53
|
@click="onDrillUp"
|
|
54
54
|
/>
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
variant="outlined"
|
|
40
40
|
:text="drilldownBackLabel"
|
|
41
41
|
:aria-label="drilldownBackLabel"
|
|
42
|
-
:style="{ '--origam-btn---min-
|
|
42
|
+
:style="{ '--origam-btn---min-width': '0' }"
|
|
43
43
|
data-cy="origam-chart-polar-breadcrumb-back"
|
|
44
44
|
@click="onDrillUp"
|
|
45
45
|
/>
|
|
@@ -421,7 +421,6 @@ defineExpose({ rebuild, copied, codeRef });
|
|
|
421
421
|
|
|
422
422
|
.origam-code__copy--compact {
|
|
423
423
|
flex: none;
|
|
424
|
-
--origam-btn---min-height: 0;
|
|
425
424
|
--origam-btn---min-width: 0px;
|
|
426
425
|
--origam-btn---height: auto;
|
|
427
426
|
--origam-btn---padding-block: var(--origam-code__compact-copy---padding-block);
|
|
@@ -464,7 +463,6 @@ defineExpose({ rebuild, copied, codeRef });
|
|
|
464
463
|
}
|
|
465
464
|
|
|
466
465
|
.origam-code__copy {
|
|
467
|
-
--origam-btn---min-height: 0;
|
|
468
466
|
--origam-btn---min-width: 0px;
|
|
469
467
|
--origam-btn---border-radius: var(--origam-code__copy---border-radius);
|
|
470
468
|
--origam-btn---font-size: var(--origam-code__copy---font-size);
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.useStyle = useStyle;
|
|
7
7
|
var _vue = require("vue");
|
|
8
|
+
var _ssrStyle = require("../../consts/Commons/ssr-style.const.cjs");
|
|
8
9
|
var _dom = require("../../utils/Commons/dom.util.cjs");
|
|
9
10
|
var _getCurrentInstance = require("../../utils/Commons/getCurrentInstance.util.cjs");
|
|
10
11
|
var _styleTag = require("./styleTag.composable.cjs");
|
|
@@ -21,6 +22,14 @@ function toDeclarations(value) {
|
|
|
21
22
|
}
|
|
22
23
|
return [];
|
|
23
24
|
}
|
|
25
|
+
const styleSlots = /* @__PURE__ */new WeakMap();
|
|
26
|
+
function nextStyleSlot() {
|
|
27
|
+
const vm = (0, _vue.getCurrentInstance)();
|
|
28
|
+
if (!vm) return 0;
|
|
29
|
+
const slot = styleSlots.get(vm) ?? 0;
|
|
30
|
+
styleSlots.set(vm, slot + 1);
|
|
31
|
+
return slot;
|
|
32
|
+
}
|
|
24
33
|
function useStyle(styles, uniq = void 0, name = (0, _getCurrentInstance.getCurrentInstanceName)()) {
|
|
25
34
|
const fallbackId = `${name}-${(0, _getCurrentInstance.getUid)()}`;
|
|
26
35
|
const id = (0, _vue.computed)(() => {
|
|
@@ -31,13 +40,17 @@ function useStyle(styles, uniq = void 0, name = (0, _getCurrentInstance.getCurre
|
|
|
31
40
|
const stylesArray = toDeclarations(styles.value);
|
|
32
41
|
return `#${(0, _dom.escapeCssIdent)(id.value)} {${stylesArray.join(";")}}`;
|
|
33
42
|
});
|
|
43
|
+
const tagId = `${_ssrStyle.SSR_STYLE_TAG_PREFIX}${fallbackId}-${nextStyleSlot()}`;
|
|
44
|
+
(0, _vue.inject)(_ssrStyle.ORIGAM_SSR_STYLES_KEY, null)?.add(tagId, () => customCss.value);
|
|
34
45
|
const {
|
|
35
46
|
id: styleTagId,
|
|
36
47
|
css,
|
|
37
48
|
load,
|
|
38
49
|
unload,
|
|
39
50
|
isLoaded
|
|
40
|
-
} = (0, _styleTag.useStyleTag)(customCss
|
|
51
|
+
} = (0, _styleTag.useStyleTag)(customCss, {
|
|
52
|
+
id: tagId
|
|
53
|
+
});
|
|
41
54
|
(0, _vue.onMounted)(() => {
|
|
42
55
|
load();
|
|
43
56
|
});
|
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
import type { ComputedRef, MaybeRefOrGetter } from 'vue';
|
|
2
|
-
/**
|
|
3
|
-
* Build a per-instance stylesheet out of a computed style bag and inject it
|
|
4
|
-
* in `<head>`, scoped to the root element's id.
|
|
5
|
-
*
|
|
6
|
-
* `uniq` is the id the CALLER wants that root element to carry. Passing
|
|
7
|
-
* `() => props.id` is what makes a consumer-supplied `id` win over the
|
|
8
|
-
* generated one: the returned `id` is what the component binds to its root,
|
|
9
|
-
* and the generated rule targets that same id — so honouring the consumer's
|
|
10
|
-
* `id` never orphans the rule. Reactive (ref / getter) so that an `id` that
|
|
11
|
-
* appears on a later render is picked up.
|
|
12
|
-
*
|
|
13
|
-
* When the caller passes nothing (or an empty value) the generated
|
|
14
|
-
* `<name>-<uid>` id is used, exactly as before.
|
|
15
|
-
*/
|
|
16
2
|
/*********************************************************
|
|
17
3
|
* useStyle
|
|
18
4
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { computed, onMounted, toValue } from "vue";
|
|
1
|
+
import { computed, getCurrentInstance, inject, onMounted, toValue } from "vue";
|
|
2
|
+
import { ORIGAM_SSR_STYLES_KEY, SSR_STYLE_TAG_PREFIX } from "../../consts/Commons/ssr-style.const.js";
|
|
2
3
|
import { escapeCssIdent } from "../../utils/Commons/dom.util.js";
|
|
3
4
|
import { getCurrentInstanceName, getUid } from "../../utils/Commons/getCurrentInstance.util.js";
|
|
4
5
|
import { useStyleTag } from "./styleTag.composable.js";
|
|
@@ -15,6 +16,14 @@ function toDeclarations(value) {
|
|
|
15
16
|
}
|
|
16
17
|
return [];
|
|
17
18
|
}
|
|
19
|
+
const styleSlots = /* @__PURE__ */ new WeakMap();
|
|
20
|
+
function nextStyleSlot() {
|
|
21
|
+
const vm = getCurrentInstance();
|
|
22
|
+
if (!vm) return 0;
|
|
23
|
+
const slot = styleSlots.get(vm) ?? 0;
|
|
24
|
+
styleSlots.set(vm, slot + 1);
|
|
25
|
+
return slot;
|
|
26
|
+
}
|
|
18
27
|
export function useStyle(styles, uniq = void 0, name = getCurrentInstanceName()) {
|
|
19
28
|
const fallbackId = `${name}-${getUid()}`;
|
|
20
29
|
const id = computed(() => {
|
|
@@ -25,7 +34,9 @@ export function useStyle(styles, uniq = void 0, name = getCurrentInstanceName())
|
|
|
25
34
|
const stylesArray = toDeclarations(styles.value);
|
|
26
35
|
return `#${escapeCssIdent(id.value)} {${stylesArray.join(";")}}`;
|
|
27
36
|
});
|
|
28
|
-
const
|
|
37
|
+
const tagId = `${SSR_STYLE_TAG_PREFIX}${fallbackId}-${nextStyleSlot()}`;
|
|
38
|
+
inject(ORIGAM_SSR_STYLES_KEY, null)?.add(tagId, () => customCss.value);
|
|
39
|
+
const { id: styleTagId, css, load, unload, isLoaded } = useStyleTag(customCss, { id: tagId });
|
|
29
40
|
onMounted(() => {
|
|
30
41
|
load();
|
|
31
42
|
});
|
|
@@ -18,15 +18,20 @@ function useStyleTag(css, options = {}) {
|
|
|
18
18
|
} = options;
|
|
19
19
|
const cssRef = (0, _vue.shallowRef)(css);
|
|
20
20
|
let stop = () => {};
|
|
21
|
+
let tag;
|
|
21
22
|
const load = () => {
|
|
22
23
|
if (!document) return;
|
|
23
|
-
|
|
24
|
+
if (isLoaded.value) return;
|
|
25
|
+
const existing = document.getElementById(id);
|
|
26
|
+
const adoptable = existing && existing.dataset.origamStyleOwned === void 0 ? existing : void 0;
|
|
27
|
+
const el = adoptable ?? document.createElement("style");
|
|
24
28
|
if (!el.isConnected) {
|
|
25
|
-
el.id = id;
|
|
29
|
+
el.id = existing ? `${id}-${++_id}` : id;
|
|
26
30
|
if (options.media) el.media = options.media;
|
|
27
31
|
document.head.appendChild(el);
|
|
28
32
|
}
|
|
29
|
-
|
|
33
|
+
el.dataset.origamStyleOwned = "";
|
|
34
|
+
tag = el;
|
|
30
35
|
stop = (0, _vue.watch)(cssRef, value => {
|
|
31
36
|
el.textContent = value;
|
|
32
37
|
}, {
|
|
@@ -37,7 +42,8 @@ function useStyleTag(css, options = {}) {
|
|
|
37
42
|
const unload = () => {
|
|
38
43
|
if (!document || !isLoaded.value) return;
|
|
39
44
|
stop();
|
|
40
|
-
|
|
45
|
+
tag?.remove();
|
|
46
|
+
tag = void 0;
|
|
41
47
|
isLoaded.value = false;
|
|
42
48
|
};
|
|
43
49
|
if (immediate && !manual) (0, _commons2.tryOnMounted)(load);
|
|
@@ -13,18 +13,23 @@ export function useStyleTag(css, options = {}) {
|
|
|
13
13
|
const cssRef = shallowRef(css);
|
|
14
14
|
let stop = () => {
|
|
15
15
|
};
|
|
16
|
+
let tag;
|
|
16
17
|
const load = () => {
|
|
17
18
|
if (!document)
|
|
18
19
|
return;
|
|
19
|
-
|
|
20
|
+
if (isLoaded.value)
|
|
21
|
+
return;
|
|
22
|
+
const existing = document.getElementById(id);
|
|
23
|
+
const adoptable = existing && existing.dataset.origamStyleOwned === void 0 ? existing : void 0;
|
|
24
|
+
const el = adoptable ?? document.createElement("style");
|
|
20
25
|
if (!el.isConnected) {
|
|
21
|
-
el.id = id;
|
|
26
|
+
el.id = existing ? `${id}-${++_id}` : id;
|
|
22
27
|
if (options.media)
|
|
23
28
|
el.media = options.media;
|
|
24
29
|
document.head.appendChild(el);
|
|
25
30
|
}
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
el.dataset.origamStyleOwned = "";
|
|
32
|
+
tag = el;
|
|
28
33
|
stop = watch(
|
|
29
34
|
cssRef,
|
|
30
35
|
(value) => {
|
|
@@ -38,7 +43,8 @@ export function useStyleTag(css, options = {}) {
|
|
|
38
43
|
if (!document || !isLoaded.value)
|
|
39
44
|
return;
|
|
40
45
|
stop();
|
|
41
|
-
|
|
46
|
+
tag?.remove();
|
|
47
|
+
tag = void 0;
|
|
42
48
|
isLoaded.value = false;
|
|
43
49
|
};
|
|
44
50
|
if (immediate && !manual)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.SSR_STYLE_TAG_PREFIX = exports.ORIGAM_SSR_STYLES_KEY = void 0;
|
|
7
|
+
const ORIGAM_SSR_STYLES_KEY = exports.ORIGAM_SSR_STYLES_KEY = /* @__PURE__ */Symbol.for("origam:ssr-styles");
|
|
8
|
+
const SSR_STYLE_TAG_PREFIX = exports.SSR_STYLE_TAG_PREFIX = "origam-style-";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { InjectionKey } from 'vue';
|
|
2
|
+
import type { ISsrStyleCollector } from '../../interfaces/Commons/style.interface';
|
|
3
|
+
/*********************************************************
|
|
4
|
+
* ORIGAM_SSR_STYLES_KEY / SSR_STYLE_TAG_PREFIX (#1092)
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* Provide/inject key for the per-app collector the server render fills with
|
|
8
|
+
* every `useStyle()` rule. Global symbol, like the other origam keys, so two
|
|
9
|
+
* bundles of the library interoperate. `createOrigam()` provides it ONLY when
|
|
10
|
+
* there is no `document`: on the client `inject()` returns `null` and
|
|
11
|
+
* `useStyle` takes the DOM path.
|
|
12
|
+
*
|
|
13
|
+
* @description
|
|
14
|
+
* Prefix of the `id` of the `<style>` tag a `useStyle()` instance owns,
|
|
15
|
+
* followed by the instance's `useId()` value, so the tag the server renders
|
|
16
|
+
* and the tag the client looks up at mount carry the SAME id.
|
|
17
|
+
********************************************************/
|
|
18
|
+
export declare const ORIGAM_SSR_STYLES_KEY: InjectionKey<ISsrStyleCollector>;
|
|
19
|
+
export declare const SSR_STYLE_TAG_PREFIX = "origam-style-";
|
|
@@ -69,6 +69,17 @@ Object.keys(_defaults).forEach(function (key) {
|
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
|
+
var _ssrStyle = require("./Commons/ssr-style.const.cjs");
|
|
73
|
+
Object.keys(_ssrStyle).forEach(function (key) {
|
|
74
|
+
if (key === "default" || key === "__esModule") return;
|
|
75
|
+
if (key in exports && exports[key] === _ssrStyle[key]) return;
|
|
76
|
+
Object.defineProperty(exports, key, {
|
|
77
|
+
enumerable: true,
|
|
78
|
+
get: function () {
|
|
79
|
+
return _ssrStyle[key];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
72
83
|
var _density = require("./Commons/density.const.cjs");
|
|
73
84
|
Object.keys(_density).forEach(function (key) {
|
|
74
85
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -4,6 +4,7 @@ export * from './Commons/color.const';
|
|
|
4
4
|
export * from './Commons/commons.const';
|
|
5
5
|
export * from './Commons/date.const';
|
|
6
6
|
export * from './Commons/defaults.const';
|
|
7
|
+
export * from './Commons/ssr-style.const';
|
|
7
8
|
export * from './Commons/density.const';
|
|
8
9
|
export * from './Commons/dimension.const';
|
|
9
10
|
export * from './Commons/layout.const';
|
package/dist/src/consts/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./Commons/color.const.js";
|
|
|
4
4
|
export * from "./Commons/commons.const.js";
|
|
5
5
|
export * from "./Commons/date.const.js";
|
|
6
6
|
export * from "./Commons/defaults.const.js";
|
|
7
|
+
export * from "./Commons/ssr-style.const.js";
|
|
7
8
|
export * from "./Commons/density.const.js";
|
|
8
9
|
export * from "./Commons/dimension.const.js";
|
|
9
10
|
export * from "./Commons/layout.const.js";
|
|
@@ -142,12 +142,67 @@ function enforceContrast(el, enabled) {
|
|
|
142
142
|
const better = wcagRatio(WHITE, bg) >= wcagRatio(BLACK, bg) ? "#fff" : "#000";
|
|
143
143
|
el.style.setProperty("color", better, "important");
|
|
144
144
|
el.dataset.origamContrastFixed = "true";
|
|
145
|
-
|
|
145
|
+
if (process.env?.DEV) {
|
|
146
|
+
console.warn(`[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 }).`, el);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const MAX_SETTLE_PASSES = 4;
|
|
150
|
+
const COLOR_TRANSITION_PROPERTIES = /* @__PURE__ */new Set(["color", "background-color"]);
|
|
151
|
+
function declaredTransitionMs(el) {
|
|
152
|
+
const toMs = value => {
|
|
153
|
+
const n = parseFloat(value);
|
|
154
|
+
if (Number.isNaN(n)) return 0;
|
|
155
|
+
return value.trim().endsWith("ms") ? n : n * 1e3;
|
|
156
|
+
};
|
|
157
|
+
let longest = 0;
|
|
158
|
+
for (let node = el; node; node = node.parentElement) {
|
|
159
|
+
const style = getComputedStyle(node);
|
|
160
|
+
const durations = style.transitionDuration.split(",");
|
|
161
|
+
const delays = style.transitionDelay.split(",");
|
|
162
|
+
durations.forEach((duration, i) => {
|
|
163
|
+
longest = Math.max(longest, toMs(duration) + toMs(delays[i % delays.length] ?? "0"));
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return longest;
|
|
167
|
+
}
|
|
168
|
+
function runningColorTransitions(el) {
|
|
169
|
+
const found = [];
|
|
170
|
+
for (let node = el; node; node = node.parentElement) {
|
|
171
|
+
for (const animation of node.getAnimations()) {
|
|
172
|
+
const property = animation.transitionProperty;
|
|
173
|
+
if (property && COLOR_TRANSITION_PROPERTIES.has(property) && animation.playState !== "finished") {
|
|
174
|
+
found.push(animation);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return found;
|
|
179
|
+
}
|
|
180
|
+
function forceStyleRecalc(el) {
|
|
181
|
+
return getComputedStyle(el).color;
|
|
182
|
+
}
|
|
183
|
+
function settleThenEnforce(el, enabled, pending, pass = 0) {
|
|
184
|
+
if (pending.cancelled) return;
|
|
185
|
+
if (!forceStyleRecalc(el)) return;
|
|
186
|
+
if (typeof el.getAnimations === "function") {
|
|
187
|
+
const running = pass < MAX_SETTLE_PASSES ? runningColorTransitions(el) : [];
|
|
188
|
+
if (running.length) {
|
|
189
|
+
Promise.allSettled(running.map(animation => animation.finished)).then(() => settleThenEnforce(el, enabled, pending, pass + 1));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
enforceContrast(el, enabled);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const wait = declaredTransitionMs(el);
|
|
196
|
+
if (wait > 0 && pass === 0 && typeof setTimeout !== "undefined") {
|
|
197
|
+
pending.timeout = setTimeout(() => settleThenEnforce(el, enabled, pending, 1), wait);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
enforceContrast(el, enabled);
|
|
146
201
|
}
|
|
147
|
-
const SETTLE_MS = 250;
|
|
148
202
|
function cancelScheduled(el) {
|
|
149
203
|
const pending = el._contrastTimers;
|
|
150
204
|
if (!pending) return;
|
|
205
|
+
pending.cancelled = true;
|
|
151
206
|
if (pending.raf !== void 0 && typeof cancelAnimationFrame !== "undefined") {
|
|
152
207
|
cancelAnimationFrame(pending.raf);
|
|
153
208
|
}
|
|
@@ -160,10 +215,7 @@ function schedule(el, enabled) {
|
|
|
160
215
|
cancelScheduled(el);
|
|
161
216
|
const pending = {};
|
|
162
217
|
if (typeof requestAnimationFrame !== "undefined") {
|
|
163
|
-
pending.raf = requestAnimationFrame(() =>
|
|
164
|
-
}
|
|
165
|
-
if (typeof setTimeout !== "undefined") {
|
|
166
|
-
pending.timeout = setTimeout(() => enforceContrast(el, enabled), SETTLE_MS);
|
|
218
|
+
pending.raf = requestAnimationFrame(() => settleThenEnforce(el, enabled, pending));
|
|
167
219
|
}
|
|
168
220
|
el._contrastTimers = pending;
|
|
169
221
|
}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { Directive } from 'vue';
|
|
2
2
|
import type { IContrastOptions } from '../../interfaces/Commons/commons.interface';
|
|
3
3
|
export declare function setContrastConfig(value: boolean | IContrastOptions | undefined): void;
|
|
4
|
+
/**
|
|
5
|
+
* `v-contrast` — guards an element's text legibility at runtime.
|
|
6
|
+
*
|
|
7
|
+
* After the browser has resolved the design-token CSS variables, it measures
|
|
8
|
+
* the element's text colour against its painted background. When the WCAG
|
|
9
|
+
* ratio falls below the configured threshold it forces the better of
|
|
10
|
+
* black / white text (in every build) and, in dev only, logs a one-line warning explaining the swap. Toggle
|
|
11
|
+
* globally via `createOrigam({ contrast: false })`, or per-element with
|
|
12
|
+
* `v-contrast="false"`.
|
|
13
|
+
*/
|
|
4
14
|
declare const vContrast: Directive<HTMLElement, boolean | undefined>;
|
|
5
15
|
export default vContrast;
|