origam 2.35.0 → 2.36.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/CHANGELOG.md +20 -0
- package/dist/src/assets/locales/en.json +5 -0
- package/dist/src/assets/locales/fr.json +5 -0
- package/dist/src/components/Code/OrigamCode.vue +28 -9
- package/dist/src/components/CodeGroup/OrigamCodeGroup.vue +215 -0
- package/dist/src/components/CodeGroup/index.cjs +13 -0
- package/dist/src/components/CodeGroup/index.d.ts +1 -0
- package/dist/src/components/CodeGroup/index.js +1 -0
- package/dist/src/components/index.cjs +11 -0
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.js +1 -0
- package/dist/src/composables/Code/code.composable.cjs +3 -2
- package/dist/src/composables/Code/code.composable.js +3 -2
- package/dist/src/consts/CodeGroup/code-group.const.cjs +17 -0
- package/dist/src/consts/CodeGroup/code-group.const.d.ts +16 -0
- package/dist/src/consts/CodeGroup/code-group.const.js +11 -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/interfaces/Code/code.interface.d.ts +20 -0
- package/dist/src/interfaces/CodeGroup/code-group.interface.cjs +1 -0
- package/dist/src/interfaces/CodeGroup/code-group.interface.d.ts +102 -0
- package/dist/src/interfaces/CodeGroup/code-group.interface.js +0 -0
- package/dist/src/interfaces/index.cjs +11 -0
- package/dist/src/interfaces/index.d.ts +1 -0
- package/dist/src/interfaces/index.js +1 -0
- package/dist/src/types/CodeGroup/code-group.type.cjs +1 -0
- package/dist/src/types/CodeGroup/code-group.type.d.ts +2 -0
- package/dist/src/types/CodeGroup/code-group.type.js +0 -0
- package/dist/src/types/index.cjs +11 -0
- package/dist/src/types/index.d.ts +1 -0
- package/dist/src/types/index.js +1 -0
- package/dist/src/utils/CodeGroup/code-group.util.cjs +99 -0
- package/dist/src/utils/CodeGroup/code-group.util.d.ts +51 -0
- package/dist/src/utils/CodeGroup/code-group.util.js +66 -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
package/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,26 @@ This project follows [Semantic Versioning](https://semver.org).
|
|
|
18
18
|
|
|
19
19
|
## [Unreleased]
|
|
20
20
|
|
|
21
|
+
## [2.36.0] - 2026-10-19
|
|
22
|
+
|
|
23
|
+
### Added — `OrigamCodeGroup` : groupe de code à onglets (npm / pnpm / yarn) en une seule surface (#1179)
|
|
24
|
+
|
|
25
|
+
- Nouveau composant `OrigamCodeGroup`, qui réunit `OrigamTabs` et `OrigamCode` : une seule surface (bordure, rayon et élévation portés par le groupe, blocs internes aplatis et sans en-tête), un seul bouton copier qui copie le code de l'onglet actif (slot `copy` pour le remplacer), `v-model` sur l'onglet actif.
|
|
26
|
+
- Deux formes : prop `items` (`{ label, code, lang?, filename?, value? }`) ou slot avec des `<origam-code>` enfants ; le libellé de l'onglet vient de `label`, sinon de `filename`, sinon de la position.
|
|
27
|
+
- Chaque zone défilante porte un nom accessible distinct (`{groupe}, {onglet}, code block {n} of {total}, scrollable region`, clés `origam.code_group.*` en `en` et `fr`) : plus de `landmark-unique` axe entre panneaux. Donner un `label` à chaque groupe quand plusieurs se trouvent sur une même page.
|
|
28
|
+
- `OrigamCode` gagne `hideHeader`, `flat` et `scrollerAriaLabel`, utilisables seuls.
|
|
29
|
+
- Aucun nouveau token : le groupe lit `--origam-code---*`, donc un thème qui restyle `OrigamCode` restyle aussi le groupe.
|
|
30
|
+
|
|
31
|
+
## [2.35.1] - 2026-10-19
|
|
32
|
+
|
|
33
|
+
### Fixed — `OrigamCode` : un 2e bloc monté pendant un import de `shiki` en échec restait vide (#1189)
|
|
34
|
+
|
|
35
|
+
Quand `shiki` n'est pas résolvable, deux `<origam-code>` montés dans le même tick : le premier s'affichait en texte brut, le second restait **vide** (zone défilante de hauteur 0) avec un rejet de promesse non capturé. `loadHighlighter()` ne renvoyait la promesse munie de son repli qu'au premier appelant ; un appelant concurrent recevait la promesse brute, qui rejetait, et `rebuild()` n'avait qu'un `try/finally`.
|
|
36
|
+
|
|
37
|
+
- `loadHighlighter()` renvoie désormais la même promesse, déjà munie de son repli (`null` → code brut), à tous les appelants.
|
|
38
|
+
- `rebuild()` capture en plus un éventuel rejet et peint le code en clair : aucun bloc ne reste vide.
|
|
39
|
+
- Prouvé par `packages/tests/TU/components/Code/OrigamCode-concurrent-load-failure.spec.ts` (rouge sur le parent, vert après).
|
|
40
|
+
|
|
21
41
|
## [2.35.0] - 2026-10-19
|
|
22
42
|
|
|
23
43
|
### Added — `OrigamCode` : `lang` ouvert, `createOrigam({ code: { langs } })` (#1180)
|
|
@@ -175,6 +175,11 @@
|
|
|
175
175
|
"scroller_aria_label_filename": "{filename}, code block, scrollable region",
|
|
176
176
|
"scroller_aria_label_lang": "{lang} code block, scrollable region"
|
|
177
177
|
},
|
|
178
|
+
"code_group": {
|
|
179
|
+
"tabs_aria_label": "Code variants",
|
|
180
|
+
"scroller_aria_label": "{label}, code block {position} of {total}, scrollable region",
|
|
181
|
+
"scroller_aria_label_group": "{group}, {label}, code block {position} of {total}, scrollable region"
|
|
182
|
+
},
|
|
178
183
|
"qr_code": {
|
|
179
184
|
"aria_label": "QR code for {value}"
|
|
180
185
|
},
|
|
@@ -175,6 +175,11 @@
|
|
|
175
175
|
"scroller_aria_label_filename": "{filename}, bloc de code, zone défilante",
|
|
176
176
|
"scroller_aria_label_lang": "Bloc de code {lang}, zone défilante"
|
|
177
177
|
},
|
|
178
|
+
"code_group": {
|
|
179
|
+
"tabs_aria_label": "Variantes du code",
|
|
180
|
+
"scroller_aria_label": "{label}, bloc de code {position} sur {total}, zone défilante",
|
|
181
|
+
"scroller_aria_label_group": "{group}, {label}, bloc de code {position} sur {total}, zone défilante"
|
|
182
|
+
},
|
|
178
183
|
"qr_code": {
|
|
179
184
|
"aria_label": "QR code pour {value}"
|
|
180
185
|
},
|
|
@@ -124,6 +124,9 @@ const props = defineProps({
|
|
|
124
124
|
filename: { type: String, required: false, default: void 0 },
|
|
125
125
|
compact: { type: Boolean, required: false, default: false },
|
|
126
126
|
prompt: { type: String, required: false, default: void 0 },
|
|
127
|
+
hideHeader: { type: Boolean, required: false, default: false },
|
|
128
|
+
flat: { type: Boolean, required: false, default: false },
|
|
129
|
+
scrollerAriaLabel: { type: String, required: false, default: void 0 },
|
|
127
130
|
id: { type: String, required: false },
|
|
128
131
|
class: { type: [String, Array, Object], required: false },
|
|
129
132
|
style: { type: [String, Array, Object, Boolean, null], required: false, skipCheck: true },
|
|
@@ -207,6 +210,7 @@ const { typographyStyles } = useTypography(props, "code");
|
|
|
207
210
|
const { highlight } = useCode();
|
|
208
211
|
const { t } = useLocale();
|
|
209
212
|
const scrollerLabel = computed(() => {
|
|
213
|
+
if (props.scrollerAriaLabel) return props.scrollerAriaLabel;
|
|
210
214
|
if (props.filename) return t("origam.code.scroller_aria_label_filename", { filename: props.filename });
|
|
211
215
|
if (props.lang && props.lang !== CODE_LANG.PLAINTEXT) return t("origam.code.scroller_aria_label_lang", { lang: props.lang });
|
|
212
216
|
return t("origam.code.scroller_aria_label");
|
|
@@ -266,6 +270,13 @@ async function rebuild() {
|
|
|
266
270
|
const html = await highlight(formattedCode.value, props.lang);
|
|
267
271
|
if (token !== _renderToken) return;
|
|
268
272
|
paintIntoDom(html);
|
|
273
|
+
} catch (err) {
|
|
274
|
+
console.warn("[origam] OrigamCode: highlighting failed \u2014 rendering plain code.", err);
|
|
275
|
+
if (token === _renderToken) {
|
|
276
|
+
const plain = document.createElement("div");
|
|
277
|
+
plain.textContent = formattedCode.value;
|
|
278
|
+
paintIntoDom(plain.innerHTML);
|
|
279
|
+
}
|
|
269
280
|
} finally {
|
|
270
281
|
if (token === _renderToken) isHighlighting.value = false;
|
|
271
282
|
}
|
|
@@ -316,7 +327,7 @@ const copyAriaLabel = computed(
|
|
|
316
327
|
const copyBtnStyle = {
|
|
317
328
|
padding: "var(--origam-code__copy---padding-block) var(--origam-code__copy---padding-inline)"
|
|
318
329
|
};
|
|
319
|
-
const showHeader = computed(() => !props.compact && (!!props.filename || !!slots.header || props.copyable));
|
|
330
|
+
const showHeader = computed(() => !props.compact && !props.hideHeader && (!!props.filename || !!slots.header || props.copyable));
|
|
320
331
|
const compactCopyIcon = computed(() => copied.value ? "mdi-check" : "mdi-content-copy");
|
|
321
332
|
const headerTag = computed(() => props.tag === "figure" ? "figcaption" : "div");
|
|
322
333
|
const codeClasses = computed(() => [
|
|
@@ -328,21 +339,22 @@ const codeClasses = computed(() => [
|
|
|
328
339
|
"origam-code--wrap": props.wrap,
|
|
329
340
|
"origam-code--has-header": showHeader.value,
|
|
330
341
|
"origam-code--copyable": props.copyable,
|
|
331
|
-
"origam-code--max-height": props.maxHeight != null
|
|
342
|
+
"origam-code--max-height": props.maxHeight != null,
|
|
343
|
+
"origam-code--flat": props.flat
|
|
332
344
|
},
|
|
333
|
-
borderClasses.value,
|
|
334
|
-
roundedClasses.value,
|
|
335
|
-
elevationClasses.value,
|
|
345
|
+
props.flat ? [] : borderClasses.value,
|
|
346
|
+
props.flat ? [] : roundedClasses.value,
|
|
347
|
+
props.flat ? [] : elevationClasses.value,
|
|
336
348
|
paddingClasses.value,
|
|
337
|
-
marginClasses.value,
|
|
349
|
+
props.flat ? [] : marginClasses.value,
|
|
338
350
|
colorClasses.value,
|
|
339
351
|
props.class
|
|
340
352
|
]);
|
|
341
353
|
const codeStyles = computed(() => [
|
|
342
|
-
borderStyles.value,
|
|
343
|
-
roundedStyles.value,
|
|
354
|
+
props.flat ? {} : borderStyles.value,
|
|
355
|
+
props.flat ? {} : roundedStyles.value,
|
|
344
356
|
paddingStyles.value,
|
|
345
|
-
marginStyles.value,
|
|
357
|
+
props.flat ? {} : marginStyles.value,
|
|
346
358
|
colorStyles.value,
|
|
347
359
|
dimensionStyles.value,
|
|
348
360
|
typographyStyles.value,
|
|
@@ -413,6 +425,13 @@ defineExpose({ rebuild, copied, codeRef });
|
|
|
413
425
|
white-space: nowrap;
|
|
414
426
|
}
|
|
415
427
|
|
|
428
|
+
.origam-code--flat {
|
|
429
|
+
border: 0;
|
|
430
|
+
border-radius: 0;
|
|
431
|
+
box-shadow: none;
|
|
432
|
+
margin: 0;
|
|
433
|
+
}
|
|
434
|
+
|
|
416
435
|
.origam-code__prompt {
|
|
417
436
|
flex: none;
|
|
418
437
|
color: var(--origam-code__prompt---color);
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="tag"
|
|
4
|
+
:id="id"
|
|
5
|
+
:class="groupClasses"
|
|
6
|
+
:style="groupStyles"
|
|
7
|
+
>
|
|
8
|
+
<origam-tabs
|
|
9
|
+
v-model="model"
|
|
10
|
+
class="origam-code-group__tabs"
|
|
11
|
+
variant="underline"
|
|
12
|
+
:aria-label="tabsLabel"
|
|
13
|
+
data-cy="origam-code-group-tabs"
|
|
14
|
+
>
|
|
15
|
+
<origam-tab
|
|
16
|
+
v-for="item in getItems()"
|
|
17
|
+
:key="item.value"
|
|
18
|
+
:value="item.value"
|
|
19
|
+
:text="item.label"
|
|
20
|
+
/>
|
|
21
|
+
</origam-tabs>
|
|
22
|
+
|
|
23
|
+
<slot
|
|
24
|
+
v-if="copyable"
|
|
25
|
+
name="copy"
|
|
26
|
+
:copy="handleCopy"
|
|
27
|
+
:copied="copied"
|
|
28
|
+
>
|
|
29
|
+
<origam-btn
|
|
30
|
+
variant="text"
|
|
31
|
+
class="origam-code__copy origam-code-group__copy"
|
|
32
|
+
:text="copyButtonLabel"
|
|
33
|
+
:aria-label="copyAriaLabel"
|
|
34
|
+
:style="copyBtnStyle"
|
|
35
|
+
aria-live="polite"
|
|
36
|
+
data-cy="origam-code-group-copy"
|
|
37
|
+
@click="handleCopy"
|
|
38
|
+
/>
|
|
39
|
+
</slot>
|
|
40
|
+
|
|
41
|
+
<origam-tab-panels
|
|
42
|
+
v-model="model"
|
|
43
|
+
class="origam-code-group__panels"
|
|
44
|
+
:transition="false"
|
|
45
|
+
>
|
|
46
|
+
<origam-tab-panel
|
|
47
|
+
v-for="item in getItems()"
|
|
48
|
+
:key="item.value"
|
|
49
|
+
:value="item.value"
|
|
50
|
+
>
|
|
51
|
+
<component :is="item.vnode"/>
|
|
52
|
+
</origam-tab-panel>
|
|
53
|
+
</origam-tab-panels>
|
|
54
|
+
</component>
|
|
55
|
+
</template>
|
|
56
|
+
|
|
57
|
+
<script lang="ts" setup>
|
|
58
|
+
import { computed, useSlots } from "vue";
|
|
59
|
+
import OrigamBtn from "../Btn/OrigamBtn.vue";
|
|
60
|
+
import OrigamTab from "../Tabs/OrigamTab.vue";
|
|
61
|
+
import OrigamTabPanel from "../Tabs/OrigamTabPanel.vue";
|
|
62
|
+
import OrigamTabPanels from "../Tabs/OrigamTabPanels.vue";
|
|
63
|
+
import OrigamTabs from "../Tabs/OrigamTabs.vue";
|
|
64
|
+
import { useBorder } from "../../composables/Commons/border.composable";
|
|
65
|
+
import { useClipboard } from "../../composables/Clipboard/clipboard.composable";
|
|
66
|
+
import { useDimension } from "../../composables/Commons/dimension.composable";
|
|
67
|
+
import { useElevation } from "../../composables/Commons/elevation.composable";
|
|
68
|
+
import { useLocale } from "../../composables/Commons/locale.composable";
|
|
69
|
+
import { useMargin } from "../../composables/Commons/margin.composable";
|
|
70
|
+
import { useRounded } from "../../composables/Commons/rounded.composable";
|
|
71
|
+
import { useVModel } from "../../composables/Commons/vModel.composable";
|
|
72
|
+
import { CODE_DEFAULTS } from "../../consts/Code/code.const";
|
|
73
|
+
import { findCodeGroupItem, resolveCodeGroupItems } from "../../utils/CodeGroup/code-group.util";
|
|
74
|
+
const props = defineProps({
|
|
75
|
+
items: { type: Array, required: false, default: () => [] },
|
|
76
|
+
modelValue: { type: String, required: false, default: void 0 },
|
|
77
|
+
label: { type: String, required: false, default: void 0 },
|
|
78
|
+
copyable: { type: Boolean, required: false, default: true },
|
|
79
|
+
lineNumbers: { type: Boolean, required: false, default: false },
|
|
80
|
+
wrap: { type: Boolean, required: false, default: false },
|
|
81
|
+
id: { type: String, required: false },
|
|
82
|
+
class: { type: [String, Array, Object], required: false },
|
|
83
|
+
style: { type: [String, Array, Object, Boolean, null], required: false, skipCheck: true },
|
|
84
|
+
tag: { type: String, required: false, default: "figure" },
|
|
85
|
+
border: { type: [Boolean, Number, String, Array], required: false, skipCheck: true },
|
|
86
|
+
borderTop: { type: [Boolean, Number, String], required: false },
|
|
87
|
+
borderLeft: { type: [Boolean, Number, String], required: false },
|
|
88
|
+
borderBottom: { type: [Boolean, Number, String], required: false },
|
|
89
|
+
borderRight: { type: [Boolean, Number, String], required: false },
|
|
90
|
+
borderBlock: { type: [Boolean, Number, String], required: false },
|
|
91
|
+
borderInline: { type: [Boolean, Number, String], required: false },
|
|
92
|
+
borderInlineStart: { type: [Boolean, Number, String], required: false },
|
|
93
|
+
borderInlineEnd: { type: [Boolean, Number, String], required: false },
|
|
94
|
+
borderBlockStart: { type: [Boolean, Number, String], required: false },
|
|
95
|
+
borderBlockEnd: { type: [Boolean, Number, String], required: false },
|
|
96
|
+
borderColor: { type: String, required: false },
|
|
97
|
+
borderStyle: { type: String, required: false },
|
|
98
|
+
borderTopColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
99
|
+
borderRightColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
100
|
+
borderBottomColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
101
|
+
borderLeftColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
102
|
+
borderInlineStartColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
103
|
+
borderInlineEndColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
104
|
+
borderBlockStartColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
105
|
+
borderBlockEndColor: { type: [String, Object, Boolean, null], required: false, skipCheck: true },
|
|
106
|
+
rounded: { type: [Boolean, Number, String, null], required: false, skipCheck: true },
|
|
107
|
+
roundedTopRight: { type: [Boolean, Number, String], required: false },
|
|
108
|
+
roundedTopLeft: { type: [Boolean, Number, String], required: false },
|
|
109
|
+
roundedBottomLeft: { type: [Boolean, Number, String], required: false },
|
|
110
|
+
roundedBottomRight: { type: [Boolean, Number, String], required: false },
|
|
111
|
+
roundedStartStart: { type: [Boolean, Number, String], required: false },
|
|
112
|
+
roundedStartEnd: { type: [Boolean, Number, String], required: false },
|
|
113
|
+
roundedEndStart: { type: [Boolean, Number, String], required: false },
|
|
114
|
+
roundedEndEnd: { type: [Boolean, Number, String], required: false },
|
|
115
|
+
elevation: { type: [Number, String], required: false },
|
|
116
|
+
margin: { type: [Boolean, Number, String], required: false },
|
|
117
|
+
marginTop: { type: [Boolean, Number, String], required: false },
|
|
118
|
+
marginLeft: { type: [Boolean, Number, String], required: false },
|
|
119
|
+
marginBottom: { type: [Boolean, Number, String], required: false },
|
|
120
|
+
marginRight: { type: [Boolean, Number, String], required: false },
|
|
121
|
+
marginBlock: { type: [Boolean, Number, String], required: false },
|
|
122
|
+
marginInline: { type: [Boolean, Number, String], required: false },
|
|
123
|
+
marginInlineStart: { type: [Boolean, Number, String], required: false },
|
|
124
|
+
marginInlineEnd: { type: [Boolean, Number, String], required: false },
|
|
125
|
+
marginBlockStart: { type: [Boolean, Number, String], required: false },
|
|
126
|
+
marginBlockEnd: { type: [Boolean, Number, String], required: false },
|
|
127
|
+
height: { type: [Number, String], required: false },
|
|
128
|
+
maxHeight: { type: [Number, String], required: false },
|
|
129
|
+
maxWidth: { type: [Number, String], required: false },
|
|
130
|
+
minHeight: { type: [Number, String], required: false },
|
|
131
|
+
minWidth: { type: [Number, String], required: false },
|
|
132
|
+
width: { type: [Number, String], required: false }
|
|
133
|
+
});
|
|
134
|
+
const emit = defineEmits(["update:modelValue", "copy"]);
|
|
135
|
+
defineSlots();
|
|
136
|
+
const slots = useSlots();
|
|
137
|
+
const { t } = useLocale();
|
|
138
|
+
function getItems() {
|
|
139
|
+
return resolveCodeGroupItems(props.items, slots.default?.(), {
|
|
140
|
+
label: props.label,
|
|
141
|
+
lineNumbers: props.lineNumbers,
|
|
142
|
+
wrap: props.wrap,
|
|
143
|
+
t
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const model = useVModel(props, "modelValue", () => getItems()[0]?.value);
|
|
147
|
+
const tabsLabel = computed(() => props.label ?? t("origam.code_group.tabs_aria_label"));
|
|
148
|
+
const { copy, copied } = useClipboard({ feedbackDuration: CODE_DEFAULTS.copyFeedbackDurationMs });
|
|
149
|
+
async function handleCopy() {
|
|
150
|
+
const code = findCodeGroupItem(getItems(), model.value)?.code ?? "";
|
|
151
|
+
if (await copy(code)) emit("copy", code);
|
|
152
|
+
}
|
|
153
|
+
const copyButtonLabel = computed(() => copied.value ? t("origam.code.copied") : t("origam.code.copy"));
|
|
154
|
+
const copyAriaLabel = computed(() => copied.value ? t("origam.code.copied_aria_label") : t("origam.code.copy_aria_label"));
|
|
155
|
+
const copyBtnStyle = {
|
|
156
|
+
padding: "var(--origam-code__copy---padding-block) var(--origam-code__copy---padding-inline)"
|
|
157
|
+
};
|
|
158
|
+
const { borderClasses, borderStyles } = useBorder(props);
|
|
159
|
+
const { roundedClasses, roundedStyles } = useRounded(props);
|
|
160
|
+
const { elevationClasses } = useElevation(props);
|
|
161
|
+
const { marginClasses, marginStyles } = useMargin(props);
|
|
162
|
+
const { dimensionStyles } = useDimension(props);
|
|
163
|
+
const groupClasses = computed(() => [
|
|
164
|
+
"origam-code-group",
|
|
165
|
+
{ "origam-code-group--copyable": props.copyable },
|
|
166
|
+
borderClasses.value,
|
|
167
|
+
roundedClasses.value,
|
|
168
|
+
elevationClasses.value,
|
|
169
|
+
marginClasses.value,
|
|
170
|
+
props.class
|
|
171
|
+
]);
|
|
172
|
+
const groupStyles = computed(() => [
|
|
173
|
+
borderStyles.value,
|
|
174
|
+
roundedStyles.value,
|
|
175
|
+
marginStyles.value,
|
|
176
|
+
dimensionStyles.value,
|
|
177
|
+
props.style
|
|
178
|
+
]);
|
|
179
|
+
defineExpose({ copied, model });
|
|
180
|
+
</script>
|
|
181
|
+
|
|
182
|
+
<style lang="scss">
|
|
183
|
+
.origam-code-group {
|
|
184
|
+
display: grid;
|
|
185
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
186
|
+
grid-template-areas:
|
|
187
|
+
"tabs copy"
|
|
188
|
+
"panels panels";
|
|
189
|
+
align-items: center;
|
|
190
|
+
margin: 0;
|
|
191
|
+
overflow: hidden;
|
|
192
|
+
background-color: var(--origam-code__header---background-color);
|
|
193
|
+
color: var(--origam-code---color);
|
|
194
|
+
border: var(--origam-code---border-width) solid var(--origam-code---border-color);
|
|
195
|
+
border-radius: var(--origam-code---border-radius);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.origam-code-group__tabs {
|
|
199
|
+
grid-area: tabs;
|
|
200
|
+
min-inline-size: 0;
|
|
201
|
+
overflow-x: auto;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.origam-code-group__copy {
|
|
205
|
+
grid-area: copy;
|
|
206
|
+
margin-inline-end: var(--origam-code__header---padding-inline);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.origam-code-group__panels {
|
|
210
|
+
grid-area: panels;
|
|
211
|
+
min-inline-size: 0;
|
|
212
|
+
background-color: var(--origam-code---background-color);
|
|
213
|
+
border-top: var(--origam-code---border-width) solid var(--origam-code---border-color);
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "OrigamCodeGroup", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _OrigamCodeGroup.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _OrigamCodeGroup = _interopRequireDefault(require("./OrigamCodeGroup.vue"));
|
|
13
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as OrigamCodeGroup } from './OrigamCodeGroup.vue';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as OrigamCodeGroup } from "./OrigamCodeGroup.vue";
|
|
@@ -201,6 +201,17 @@ Object.keys(_Code).forEach(function (key) {
|
|
|
201
201
|
}
|
|
202
202
|
});
|
|
203
203
|
});
|
|
204
|
+
var _CodeGroup = require("./CodeGroup/index.cjs");
|
|
205
|
+
Object.keys(_CodeGroup).forEach(function (key) {
|
|
206
|
+
if (key === "default" || key === "__esModule") return;
|
|
207
|
+
if (key in exports && exports[key] === _CodeGroup[key]) return;
|
|
208
|
+
Object.defineProperty(exports, key, {
|
|
209
|
+
enumerable: true,
|
|
210
|
+
get: function () {
|
|
211
|
+
return _CodeGroup[key];
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|
|
204
215
|
var _ColorPicker = require("./ColorPicker/index.cjs");
|
|
205
216
|
Object.keys(_ColorPicker).forEach(function (key) {
|
|
206
217
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -16,6 +16,7 @@ export * from "./Chip/index.js";
|
|
|
16
16
|
export * from "./ClientOnly/index.js";
|
|
17
17
|
export * from "./Clipboard/index.js";
|
|
18
18
|
export * from "./Code/index.js";
|
|
19
|
+
export * from "./CodeGroup/index.js";
|
|
19
20
|
export * from "./ColorPicker/index.js";
|
|
20
21
|
export * from "./ColorPickerField/index.js";
|
|
21
22
|
export * from "./CommandPalette/index.js";
|
|
@@ -37,7 +37,7 @@ function lruSet(key, value) {
|
|
|
37
37
|
async function loadHighlighter(loader, langs) {
|
|
38
38
|
if (_highlighterUnavailable) return null;
|
|
39
39
|
if (_highlighterPromise) return _highlighterPromise;
|
|
40
|
-
|
|
40
|
+
const raw = (async () => {
|
|
41
41
|
const shiki = loader ? await loader() : await Promise.resolve().then(() => require("shiki"));
|
|
42
42
|
const highlighter = await shiki.createHighlighter({
|
|
43
43
|
themes: [_code.CODE_LIGHT_THEME, _code.CODE_DARK_THEME],
|
|
@@ -46,7 +46,7 @@ async function loadHighlighter(loader, langs) {
|
|
|
46
46
|
_highlighterReady = true;
|
|
47
47
|
return highlighter;
|
|
48
48
|
})();
|
|
49
|
-
|
|
49
|
+
_highlighterPromise = raw.catch(err => {
|
|
50
50
|
_highlighterUnavailable = true;
|
|
51
51
|
_highlighterPromise = null;
|
|
52
52
|
if (!_unavailableWarned) {
|
|
@@ -55,6 +55,7 @@ async function loadHighlighter(loader, langs) {
|
|
|
55
55
|
}
|
|
56
56
|
return null;
|
|
57
57
|
});
|
|
58
|
+
return _highlighterPromise;
|
|
58
59
|
}
|
|
59
60
|
function resolveLang(lang, hasCustomHighlighter, extraLangs) {
|
|
60
61
|
if (hasCustomHighlighter) return lang;
|
|
@@ -30,7 +30,7 @@ function lruSet(key, value) {
|
|
|
30
30
|
async function loadHighlighter(loader, langs) {
|
|
31
31
|
if (_highlighterUnavailable) return null;
|
|
32
32
|
if (_highlighterPromise) return _highlighterPromise;
|
|
33
|
-
|
|
33
|
+
const raw = (async () => {
|
|
34
34
|
const shiki = loader ? await loader() : await import(
|
|
35
35
|
/* @vite-ignore */
|
|
36
36
|
"shiki"
|
|
@@ -42,7 +42,7 @@ async function loadHighlighter(loader, langs) {
|
|
|
42
42
|
_highlighterReady = true;
|
|
43
43
|
return highlighter;
|
|
44
44
|
})();
|
|
45
|
-
|
|
45
|
+
_highlighterPromise = raw.catch((err) => {
|
|
46
46
|
_highlighterUnavailable = true;
|
|
47
47
|
_highlighterPromise = null;
|
|
48
48
|
if (!_unavailableWarned) {
|
|
@@ -54,6 +54,7 @@ async function loadHighlighter(loader, langs) {
|
|
|
54
54
|
}
|
|
55
55
|
return null;
|
|
56
56
|
});
|
|
57
|
+
return _highlighterPromise;
|
|
57
58
|
}
|
|
58
59
|
function resolveLang(lang, hasCustomHighlighter, extraLangs) {
|
|
59
60
|
if (hasCustomHighlighter) return lang;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.CODE_GROUP_EMBED_PROPS = exports.CODE_GROUP_DEFAULTS = void 0;
|
|
7
|
+
const CODE_GROUP_EMBED_PROPS = exports.CODE_GROUP_EMBED_PROPS = {
|
|
8
|
+
hideHeader: true,
|
|
9
|
+
flat: true,
|
|
10
|
+
copyable: false
|
|
11
|
+
};
|
|
12
|
+
const CODE_GROUP_DEFAULTS = exports.CODE_GROUP_DEFAULTS = {
|
|
13
|
+
tag: "figure",
|
|
14
|
+
copyable: true,
|
|
15
|
+
lineNumbers: false,
|
|
16
|
+
wrap: false
|
|
17
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ICodeProps } from '../../interfaces/Code/code.interface';
|
|
2
|
+
/*********************************************************
|
|
3
|
+
* CODE_GROUP_EMBED_PROPS
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* What `<OrigamCodeGroup>` forces on every `<OrigamCode>` it hosts: the tab
|
|
7
|
+
* already shows the label, the group already owns the one surface and the
|
|
8
|
+
* one copy button.
|
|
9
|
+
********************************************************/
|
|
10
|
+
export declare const CODE_GROUP_EMBED_PROPS: Pick<ICodeProps, 'hideHeader' | 'flat' | 'copyable'>;
|
|
11
|
+
export declare const CODE_GROUP_DEFAULTS: {
|
|
12
|
+
readonly tag: "figure";
|
|
13
|
+
readonly copyable: true;
|
|
14
|
+
readonly lineNumbers: false;
|
|
15
|
+
readonly wrap: false;
|
|
16
|
+
};
|
|
@@ -366,6 +366,17 @@ Object.keys(_code).forEach(function (key) {
|
|
|
366
366
|
}
|
|
367
367
|
});
|
|
368
368
|
});
|
|
369
|
+
var _codeGroup = require("./CodeGroup/code-group.const.cjs");
|
|
370
|
+
Object.keys(_codeGroup).forEach(function (key) {
|
|
371
|
+
if (key === "default" || key === "__esModule") return;
|
|
372
|
+
if (key in exports && exports[key] === _codeGroup[key]) return;
|
|
373
|
+
Object.defineProperty(exports, key, {
|
|
374
|
+
enumerable: true,
|
|
375
|
+
get: function () {
|
|
376
|
+
return _codeGroup[key];
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
});
|
|
369
380
|
var _selectionControl = require("./SelectionControl/selection-control.const.cjs");
|
|
370
381
|
Object.keys(_selectionControl).forEach(function (key) {
|
|
371
382
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -31,6 +31,7 @@ export * from './Commons/vmodel.const';
|
|
|
31
31
|
export * from './Commons/forwardRefs.const';
|
|
32
32
|
export * from './ColorPicker/color-picker.const';
|
|
33
33
|
export * from './Code/code.const';
|
|
34
|
+
export * from './CodeGroup/code-group.const';
|
|
34
35
|
export * from './SelectionControl/selection-control.const';
|
|
35
36
|
export * from './Snackbar/snackbar-group.const';
|
|
36
37
|
export * from './Snackbar/snackbar.const';
|
package/dist/src/consts/index.js
CHANGED
|
@@ -31,6 +31,7 @@ export * from "./Commons/vmodel.const.js";
|
|
|
31
31
|
export * from "./Commons/forwardRefs.const.js";
|
|
32
32
|
export * from "./ColorPicker/color-picker.const.js";
|
|
33
33
|
export * from "./Code/code.const.js";
|
|
34
|
+
export * from "./CodeGroup/code-group.const.js";
|
|
34
35
|
export * from "./SelectionControl/selection-control.const.js";
|
|
35
36
|
export * from "./Snackbar/snackbar-group.const.js";
|
|
36
37
|
export * from "./Snackbar/snackbar.const.js";
|
|
@@ -88,7 +88,27 @@ export interface ICodeProps extends ICommonsComponentProps, ITagProps, IBorderPr
|
|
|
88
88
|
* Most useful paired with `compact` for an install-command pill.
|
|
89
89
|
*/
|
|
90
90
|
prompt?: string;
|
|
91
|
+
hideHeader?: boolean;
|
|
92
|
+
flat?: boolean;
|
|
93
|
+
scrollerAriaLabel?: string;
|
|
91
94
|
}
|
|
95
|
+
/*********************************************************
|
|
96
|
+
* Embedding props (`hideHeader`, `flat`, `scrollerAriaLabel`)
|
|
97
|
+
*
|
|
98
|
+
* @description
|
|
99
|
+
* `hideHeader` removes the header bar (filename / language badge / copy
|
|
100
|
+
* button) whatever `filename`, `copyable` or the `header` slot say.
|
|
101
|
+
* @description
|
|
102
|
+
* `flat` flattens the block into its host: no border, no radius, no
|
|
103
|
+
* elevation, no outer margin, so the host owns the one visible surface.
|
|
104
|
+
* @description
|
|
105
|
+
* `scrollerAriaLabel` is the accessible name of the scrollable region. Left
|
|
106
|
+
* out, it is derived from `filename`, then `lang`; set it when several blocks
|
|
107
|
+
* of the same language share a page.
|
|
108
|
+
* @description
|
|
109
|
+
* The three exist so a block can sit inside `<OrigamCodeGroup>`, a tab already
|
|
110
|
+
* showing the label and the group owning the surface and the copy button.
|
|
111
|
+
********************************************************/
|
|
92
112
|
/*********************************************************
|
|
93
113
|
* ICodeOptions
|
|
94
114
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { VNode } from 'vue';
|
|
2
|
+
import type { IBorderProps } from '../Commons/border.interface';
|
|
3
|
+
import type { ICommonsComponentEmits, ICommonsComponentProps, ITagProps } from '../Commons/commons.interface';
|
|
4
|
+
import type { IDimensionProps } from '../Commons/dimension.interface';
|
|
5
|
+
import type { IElevationProps } from '../Commons/elevation.interface';
|
|
6
|
+
import type { IMarginProps } from '../Commons/margin.interface';
|
|
7
|
+
import type { IRoundedProps } from '../Commons/rounded.interface';
|
|
8
|
+
import type { TCodeLangOpen } from '../../types/Code/code.type';
|
|
9
|
+
/*********************************************************
|
|
10
|
+
* ICodeGroupItem
|
|
11
|
+
*
|
|
12
|
+
* @description
|
|
13
|
+
* One tab of an `<OrigamCodeGroup>` in its `items` form: the label shown on
|
|
14
|
+
* the tab and the code shown in its panel.
|
|
15
|
+
********************************************************/
|
|
16
|
+
export interface ICodeGroupItem {
|
|
17
|
+
label: string;
|
|
18
|
+
code: string;
|
|
19
|
+
lang?: TCodeLangOpen;
|
|
20
|
+
filename?: string;
|
|
21
|
+
value?: string;
|
|
22
|
+
}
|
|
23
|
+
/*********************************************************
|
|
24
|
+
* ICodeGroupResolvedItem
|
|
25
|
+
*
|
|
26
|
+
* @description
|
|
27
|
+
* An `ICodeGroupItem` once the group has settled its `value` and, in the
|
|
28
|
+
* slot form, kept the child `<OrigamCode>` vnode to render in the panel.
|
|
29
|
+
********************************************************/
|
|
30
|
+
export interface ICodeGroupResolvedItem extends Required<Pick<ICodeGroupItem, 'label' | 'code' | 'value'>>, Pick<ICodeGroupItem, 'lang' | 'filename'> {
|
|
31
|
+
vnode?: VNode;
|
|
32
|
+
}
|
|
33
|
+
/*********************************************************
|
|
34
|
+
* ICodeGroupRenderedItem
|
|
35
|
+
*
|
|
36
|
+
* @description
|
|
37
|
+
* A resolved item whose `vnode` is the `<OrigamCode>` to render in the panel,
|
|
38
|
+
* already flattened, header-less and named. Built by `resolveCodeGroupItems`.
|
|
39
|
+
********************************************************/
|
|
40
|
+
export interface ICodeGroupRenderedItem extends Omit<ICodeGroupResolvedItem, 'vnode'> {
|
|
41
|
+
vnode: VNode;
|
|
42
|
+
}
|
|
43
|
+
/*********************************************************
|
|
44
|
+
* ICodeGroupResolveOptions
|
|
45
|
+
*
|
|
46
|
+
* @description
|
|
47
|
+
* What `resolveCodeGroupItems` needs from the group: its `label` and `t` to
|
|
48
|
+
* name each scroller, and `lineNumbers` / `wrap` to forward to every block.
|
|
49
|
+
********************************************************/
|
|
50
|
+
export interface ICodeGroupResolveOptions {
|
|
51
|
+
label?: string;
|
|
52
|
+
lineNumbers: boolean;
|
|
53
|
+
wrap: boolean;
|
|
54
|
+
t: (key: string, ...params: unknown[]) => string;
|
|
55
|
+
}
|
|
56
|
+
/*********************************************************
|
|
57
|
+
* ICodeGroupProps
|
|
58
|
+
*
|
|
59
|
+
* @description
|
|
60
|
+
* Props for `<OrigamCodeGroup>` — tabbed code blocks (npm / pnpm / yarn)
|
|
61
|
+
* drawn as ONE surface with one shared copy button. Fed either by `items`
|
|
62
|
+
* or by `<origam-code>` children in the default slot (the tab label comes
|
|
63
|
+
* from the child's `label`, else its `filename`).
|
|
64
|
+
* @description
|
|
65
|
+
* `modelValue` is the `value` of the active tab (default: the first tab).
|
|
66
|
+
* `label` is the accessible name of the tab list (default: a localised
|
|
67
|
+
* generic name). `copyable`, `lineNumbers` and `wrap` apply to the whole
|
|
68
|
+
* group. `items` is ignored when the default slot holds code blocks.
|
|
69
|
+
********************************************************/
|
|
70
|
+
export interface ICodeGroupProps extends ICommonsComponentProps, ITagProps, IBorderProps, IRoundedProps, IElevationProps, IMarginProps, IDimensionProps {
|
|
71
|
+
items?: ICodeGroupItem[];
|
|
72
|
+
modelValue?: string;
|
|
73
|
+
label?: string;
|
|
74
|
+
copyable?: boolean;
|
|
75
|
+
lineNumbers?: boolean;
|
|
76
|
+
wrap?: boolean;
|
|
77
|
+
}
|
|
78
|
+
/*********************************************************
|
|
79
|
+
* ICodeGroupEmits
|
|
80
|
+
*
|
|
81
|
+
* @description
|
|
82
|
+
* `update:modelValue` carries the new active tab `value`; `copy` carries the
|
|
83
|
+
* code of the tab that was copied.
|
|
84
|
+
********************************************************/
|
|
85
|
+
export interface ICodeGroupEmits extends ICommonsComponentEmits {
|
|
86
|
+
(e: 'update:modelValue', value: string): void;
|
|
87
|
+
(e: 'copy', code: string): void;
|
|
88
|
+
}
|
|
89
|
+
/*********************************************************
|
|
90
|
+
* ICodeGroupSlots
|
|
91
|
+
*
|
|
92
|
+
* @description
|
|
93
|
+
* `default` takes the `<origam-code>` children, one per tab, when `items` is
|
|
94
|
+
* not used. `copy` replaces the shared copy button.
|
|
95
|
+
********************************************************/
|
|
96
|
+
export interface ICodeGroupSlots {
|
|
97
|
+
default?: () => any;
|
|
98
|
+
copy?: (data: {
|
|
99
|
+
copy: () => Promise<void>;
|
|
100
|
+
copied: boolean;
|
|
101
|
+
}) => any;
|
|
102
|
+
}
|
|
File without changes
|
|
@@ -399,6 +399,17 @@ Object.keys(_code).forEach(function (key) {
|
|
|
399
399
|
}
|
|
400
400
|
});
|
|
401
401
|
});
|
|
402
|
+
var _codeGroup = require("./CodeGroup/code-group.interface.cjs");
|
|
403
|
+
Object.keys(_codeGroup).forEach(function (key) {
|
|
404
|
+
if (key === "default" || key === "__esModule") return;
|
|
405
|
+
if (key in exports && exports[key] === _codeGroup[key]) return;
|
|
406
|
+
Object.defineProperty(exports, key, {
|
|
407
|
+
enumerable: true,
|
|
408
|
+
get: function () {
|
|
409
|
+
return _codeGroup[key];
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
});
|
|
402
413
|
var _colorPicker = require("./ColorPicker/color-picker.interface.cjs");
|
|
403
414
|
Object.keys(_colorPicker).forEach(function (key) {
|
|
404
415
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -34,6 +34,7 @@ export * from './Chip/chip-group.interface';
|
|
|
34
34
|
export * from './ClientOnly/client-only.interface';
|
|
35
35
|
export * from './Clipboard/clipboard.interface';
|
|
36
36
|
export * from './Code/code.interface';
|
|
37
|
+
export * from './CodeGroup/code-group.interface';
|
|
37
38
|
export * from './ColorPicker/color-picker.interface';
|
|
38
39
|
export * from './ColorPicker/color-picker-canvas.interface';
|
|
39
40
|
export * from './ConfirmWrapper/confirm-wrapper.interface';
|
|
@@ -34,6 +34,7 @@ export * from "./Chip/chip-group.interface.js";
|
|
|
34
34
|
export * from "./ClientOnly/client-only.interface.js";
|
|
35
35
|
export * from "./Clipboard/clipboard.interface.js";
|
|
36
36
|
export * from "./Code/code.interface.js";
|
|
37
|
+
export * from "./CodeGroup/code-group.interface.js";
|
|
37
38
|
export * from "./ColorPicker/color-picker.interface.js";
|
|
38
39
|
export * from "./ColorPicker/color-picker-canvas.interface.js";
|
|
39
40
|
export * from "./ConfirmWrapper/confirm-wrapper.interface.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
package/dist/src/types/index.cjs
CHANGED
|
@@ -333,6 +333,17 @@ Object.keys(_code).forEach(function (key) {
|
|
|
333
333
|
}
|
|
334
334
|
});
|
|
335
335
|
});
|
|
336
|
+
var _codeGroup = require("./CodeGroup/code-group.type.cjs");
|
|
337
|
+
Object.keys(_codeGroup).forEach(function (key) {
|
|
338
|
+
if (key === "default" || key === "__esModule") return;
|
|
339
|
+
if (key in exports && exports[key] === _codeGroup[key]) return;
|
|
340
|
+
Object.defineProperty(exports, key, {
|
|
341
|
+
enumerable: true,
|
|
342
|
+
get: function () {
|
|
343
|
+
return _codeGroup[key];
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
});
|
|
336
347
|
var _colorPicker = require("./ColorPicker/color-picker.type.cjs");
|
|
337
348
|
Object.keys(_colorPicker).forEach(function (key) {
|
|
338
349
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -28,6 +28,7 @@ export * from './Chip/chip-group.type';
|
|
|
28
28
|
export * from './ClientOnly/client-only.type';
|
|
29
29
|
export * from './Clipboard/clipboard.type';
|
|
30
30
|
export * from './Code/code.type';
|
|
31
|
+
export * from './CodeGroup/code-group.type';
|
|
31
32
|
export * from './ColorPicker/color-picker.type';
|
|
32
33
|
export * from './ColorPicker/color-picker-canvas.type';
|
|
33
34
|
export * from './ColorPicker/color-picker-preview.type';
|
package/dist/src/types/index.js
CHANGED
|
@@ -28,6 +28,7 @@ export * from "./Chip/chip-group.type.js";
|
|
|
28
28
|
export * from "./ClientOnly/client-only.type.js";
|
|
29
29
|
export * from "./Clipboard/clipboard.type.js";
|
|
30
30
|
export * from "./Code/code.type.js";
|
|
31
|
+
export * from "./CodeGroup/code-group.type.js";
|
|
31
32
|
export * from "./ColorPicker/color-picker.type.js";
|
|
32
33
|
export * from "./ColorPicker/color-picker-canvas.type.js";
|
|
33
34
|
export * from "./ColorPicker/color-picker-preview.type.js";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.extractCodeGroupText = extractCodeGroupText;
|
|
7
|
+
exports.findCodeGroupItem = findCodeGroupItem;
|
|
8
|
+
exports.flattenCodeGroupVNodes = flattenCodeGroupVNodes;
|
|
9
|
+
exports.resolveCodeGroupItems = resolveCodeGroupItems;
|
|
10
|
+
exports.resolveCodeGroupSlotItems = resolveCodeGroupSlotItems;
|
|
11
|
+
var _vue = require("vue");
|
|
12
|
+
var _OrigamCode = _interopRequireDefault(require("../../components/Code/OrigamCode.vue"));
|
|
13
|
+
var _codeGroup = require("../../consts/CodeGroup/code-group.const.cjs");
|
|
14
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
function flattenCodeGroupVNodes(nodes) {
|
|
16
|
+
const out = [];
|
|
17
|
+
for (const node of nodes ?? []) {
|
|
18
|
+
if (node.type === _vue.Fragment && Array.isArray(node.children)) {
|
|
19
|
+
out.push(...flattenCodeGroupVNodes(node.children));
|
|
20
|
+
} else if (node.type !== _vue.Comment && node.type !== _vue.Text) {
|
|
21
|
+
out.push(node);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
function extractCodeGroupText(node) {
|
|
27
|
+
const children = node.children;
|
|
28
|
+
const raw = typeof children === "object" && children !== null && !Array.isArray(children) ? children.default?.() : children;
|
|
29
|
+
const parts = [];
|
|
30
|
+
const visit = value => {
|
|
31
|
+
if (value == null || typeof value === "boolean") return;
|
|
32
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
33
|
+
parts.push(String(value));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(value)) {
|
|
37
|
+
value.forEach(visit);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
visit(value.children);
|
|
41
|
+
};
|
|
42
|
+
visit(raw);
|
|
43
|
+
return parts.join("").replace(/^\n+/, "").replace(/\n+$/, "");
|
|
44
|
+
}
|
|
45
|
+
function resolveCodeGroupSlotItems(nodes) {
|
|
46
|
+
return flattenCodeGroupVNodes(nodes).map((vnode, index) => {
|
|
47
|
+
const attrs = vnode.props ?? {};
|
|
48
|
+
const label = String(attrs.label ?? attrs.filename ?? index + 1);
|
|
49
|
+
return {
|
|
50
|
+
label,
|
|
51
|
+
value: String(attrs.value ?? label),
|
|
52
|
+
code: typeof attrs.code === "string" ? attrs.code : extractCodeGroupText(vnode),
|
|
53
|
+
lang: attrs.lang,
|
|
54
|
+
filename: attrs.filename,
|
|
55
|
+
vnode
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function resolveCodeGroupItems(items, nodes, options) {
|
|
60
|
+
const fromSlot = resolveCodeGroupSlotItems(nodes);
|
|
61
|
+
const source = fromSlot.length > 0 ? fromSlot : items.map(item => ({
|
|
62
|
+
...item,
|
|
63
|
+
value: item.value ?? item.label
|
|
64
|
+
}));
|
|
65
|
+
return source.map((item, index) => {
|
|
66
|
+
const params = {
|
|
67
|
+
label: item.label,
|
|
68
|
+
position: index + 1,
|
|
69
|
+
total: source.length
|
|
70
|
+
};
|
|
71
|
+
const scrollerAriaLabel = options.label ? options.t("origam.code_group.scroller_aria_label_group", {
|
|
72
|
+
...params,
|
|
73
|
+
group: options.label
|
|
74
|
+
}) : options.t("origam.code_group.scroller_aria_label", params);
|
|
75
|
+
const embed = {
|
|
76
|
+
..._codeGroup.CODE_GROUP_EMBED_PROPS,
|
|
77
|
+
lineNumbers: options.lineNumbers || void 0,
|
|
78
|
+
wrap: options.wrap || void 0,
|
|
79
|
+
scrollerAriaLabel
|
|
80
|
+
};
|
|
81
|
+
const vnode = item.vnode ? (0, _vue.cloneVNode)(item.vnode, {
|
|
82
|
+
...embed,
|
|
83
|
+
label: void 0,
|
|
84
|
+
value: void 0
|
|
85
|
+
}) : (0, _vue.h)(_OrigamCode.default, {
|
|
86
|
+
code: item.code,
|
|
87
|
+
lang: item.lang,
|
|
88
|
+
filename: item.filename,
|
|
89
|
+
...embed
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
...item,
|
|
93
|
+
vnode
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function findCodeGroupItem(items, value) {
|
|
98
|
+
return items.find(item => item.value === value) ?? items[0];
|
|
99
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { VNode } from 'vue';
|
|
2
|
+
import type { ICodeGroupRenderedItem, ICodeGroupResolvedItem, ICodeGroupResolveOptions } from '../../interfaces/CodeGroup/code-group.interface';
|
|
3
|
+
/*********************************************************
|
|
4
|
+
* flattenCodeGroupVNodes
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* Walks a default-slot vnode list, going through fragments (`v-for`), and
|
|
8
|
+
* returns the component vnodes only: comments and whitespace text are the
|
|
9
|
+
* template's noise, not tabs.
|
|
10
|
+
********************************************************/
|
|
11
|
+
export declare function flattenCodeGroupVNodes(nodes: VNode[] | undefined): VNode[];
|
|
12
|
+
/*********************************************************
|
|
13
|
+
* extractCodeGroupText
|
|
14
|
+
*
|
|
15
|
+
* @description
|
|
16
|
+
* Text content of a child's default slot, used when the block gives its code
|
|
17
|
+
* in the slot rather than in the `code` prop (same rule as `<OrigamCode>`:
|
|
18
|
+
* leading and trailing blank lines dropped).
|
|
19
|
+
********************************************************/
|
|
20
|
+
export declare function extractCodeGroupText(node: VNode): string;
|
|
21
|
+
/*********************************************************
|
|
22
|
+
* resolveCodeGroupSlotItems
|
|
23
|
+
*
|
|
24
|
+
* @description
|
|
25
|
+
* Builds the tabs of the slot form. The label is the child's `label`, else its
|
|
26
|
+
* `filename`, else its position, so a block is never left without a tab.
|
|
27
|
+
********************************************************/
|
|
28
|
+
export declare function resolveCodeGroupSlotItems(nodes: VNode[] | undefined): ICodeGroupResolvedItem[];
|
|
29
|
+
/*********************************************************
|
|
30
|
+
* resolveCodeGroupItems
|
|
31
|
+
*
|
|
32
|
+
* @description
|
|
33
|
+
* One list for both forms of `<OrigamCodeGroup>`: the code blocks of the
|
|
34
|
+
* default slot win, `items` is the fallback. Every item comes back with the
|
|
35
|
+
* `<OrigamCode>` vnode to render, already flattened, header-less and named
|
|
36
|
+
* after the group `label`, its tab and its position — so the component does
|
|
37
|
+
* no per-item work in its template.
|
|
38
|
+
* @description
|
|
39
|
+
* `items` is typed `readonly unknown[]` on purpose: the compiled `.vue` that
|
|
40
|
+
* `nuxt typecheck` reads (`packages/ds/dist`) has its types stripped, so the
|
|
41
|
+
* prop reaches this call as `unknown[]` and an `ICodeGroupItem[]` parameter
|
|
42
|
+
* would add one error to the marketing type-check ratchet.
|
|
43
|
+
********************************************************/
|
|
44
|
+
export declare function resolveCodeGroupItems(items: readonly unknown[], nodes: VNode[] | undefined, options: ICodeGroupResolveOptions): ICodeGroupRenderedItem[];
|
|
45
|
+
/*********************************************************
|
|
46
|
+
* findCodeGroupItem
|
|
47
|
+
*
|
|
48
|
+
* @description
|
|
49
|
+
* The item whose `value` is the active one, the first item when none matches.
|
|
50
|
+
********************************************************/
|
|
51
|
+
export declare function findCodeGroupItem(items: ICodeGroupRenderedItem[], value: unknown): ICodeGroupRenderedItem | undefined;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { cloneVNode, Comment, Fragment, h, Text } from "vue";
|
|
2
|
+
import OrigamCode from "../../components/Code/OrigamCode.vue";
|
|
3
|
+
import { CODE_GROUP_EMBED_PROPS } from "../../consts/CodeGroup/code-group.const.js";
|
|
4
|
+
export function flattenCodeGroupVNodes(nodes) {
|
|
5
|
+
const out = [];
|
|
6
|
+
for (const node of nodes ?? []) {
|
|
7
|
+
if (node.type === Fragment && Array.isArray(node.children)) {
|
|
8
|
+
out.push(...flattenCodeGroupVNodes(node.children));
|
|
9
|
+
} else if (node.type !== Comment && node.type !== Text) {
|
|
10
|
+
out.push(node);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
export function extractCodeGroupText(node) {
|
|
16
|
+
const children = node.children;
|
|
17
|
+
const raw = typeof children === "object" && children !== null && !Array.isArray(children) ? children.default?.() : children;
|
|
18
|
+
const parts = [];
|
|
19
|
+
const visit = (value) => {
|
|
20
|
+
if (value == null || typeof value === "boolean") return;
|
|
21
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
22
|
+
parts.push(String(value));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(value)) {
|
|
26
|
+
value.forEach(visit);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
visit(value.children);
|
|
30
|
+
};
|
|
31
|
+
visit(raw);
|
|
32
|
+
return parts.join("").replace(/^\n+/, "").replace(/\n+$/, "");
|
|
33
|
+
}
|
|
34
|
+
export function resolveCodeGroupSlotItems(nodes) {
|
|
35
|
+
return flattenCodeGroupVNodes(nodes).map((vnode, index) => {
|
|
36
|
+
const attrs = vnode.props ?? {};
|
|
37
|
+
const label = String(attrs.label ?? attrs.filename ?? index + 1);
|
|
38
|
+
return {
|
|
39
|
+
label,
|
|
40
|
+
value: String(attrs.value ?? label),
|
|
41
|
+
code: typeof attrs.code === "string" ? attrs.code : extractCodeGroupText(vnode),
|
|
42
|
+
lang: attrs.lang,
|
|
43
|
+
filename: attrs.filename,
|
|
44
|
+
vnode
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function resolveCodeGroupItems(items, nodes, options) {
|
|
49
|
+
const fromSlot = resolveCodeGroupSlotItems(nodes);
|
|
50
|
+
const source = fromSlot.length > 0 ? fromSlot : items.map((item) => ({ ...item, value: item.value ?? item.label }));
|
|
51
|
+
return source.map((item, index) => {
|
|
52
|
+
const params = { label: item.label, position: index + 1, total: source.length };
|
|
53
|
+
const scrollerAriaLabel = options.label ? options.t("origam.code_group.scroller_aria_label_group", { ...params, group: options.label }) : options.t("origam.code_group.scroller_aria_label", params);
|
|
54
|
+
const embed = {
|
|
55
|
+
...CODE_GROUP_EMBED_PROPS,
|
|
56
|
+
lineNumbers: options.lineNumbers || void 0,
|
|
57
|
+
wrap: options.wrap || void 0,
|
|
58
|
+
scrollerAriaLabel
|
|
59
|
+
};
|
|
60
|
+
const vnode = item.vnode ? cloneVNode(item.vnode, { ...embed, label: void 0, value: void 0 }) : h(OrigamCode, { code: item.code, lang: item.lang, filename: item.filename, ...embed });
|
|
61
|
+
return { ...item, vnode };
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export function findCodeGroupItem(items, value) {
|
|
65
|
+
return items.find((item) => item.value === value) ?? items[0];
|
|
66
|
+
}
|
package/dist/src/utils/index.cjs
CHANGED
|
@@ -696,6 +696,17 @@ Object.keys(_parseHighlightLines).forEach(function (key) {
|
|
|
696
696
|
}
|
|
697
697
|
});
|
|
698
698
|
});
|
|
699
|
+
var _codeGroup = require("./CodeGroup/code-group.util.cjs");
|
|
700
|
+
Object.keys(_codeGroup).forEach(function (key) {
|
|
701
|
+
if (key === "default" || key === "__esModule") return;
|
|
702
|
+
if (key in exports && exports[key] === _codeGroup[key]) return;
|
|
703
|
+
Object.defineProperty(exports, key, {
|
|
704
|
+
enumerable: true,
|
|
705
|
+
get: function () {
|
|
706
|
+
return _codeGroup[key];
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
});
|
|
699
710
|
var _sanitizeHtml = require("./TextareaField/sanitize-html.util.cjs");
|
|
700
711
|
Object.keys(_sanitizeHtml).forEach(function (key) {
|
|
701
712
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -61,6 +61,7 @@ export * from './DataTable/slot-name.util';
|
|
|
61
61
|
export * from './DataTable/skeleton-cell.util';
|
|
62
62
|
export * from './CommandPalette/fuzzy-match.util';
|
|
63
63
|
export * from './Code/parse-highlight-lines.util';
|
|
64
|
+
export * from './CodeGroup/code-group.util';
|
|
64
65
|
export * from './TextareaField/sanitize-html.util';
|
|
65
66
|
export * from './TextareaField/html-to-markdown.util';
|
|
66
67
|
export * from './Commons/apply-mask.util';
|
package/dist/src/utils/index.js
CHANGED
|
@@ -61,6 +61,7 @@ export * from "./DataTable/slot-name.util.js";
|
|
|
61
61
|
export * from "./DataTable/skeleton-cell.util.js";
|
|
62
62
|
export * from "./CommandPalette/fuzzy-match.util.js";
|
|
63
63
|
export * from "./Code/parse-highlight-lines.util.js";
|
|
64
|
+
export * from "./CodeGroup/code-group.util.js";
|
|
64
65
|
export * from "./TextareaField/sanitize-html.util.js";
|
|
65
66
|
export * from "./TextareaField/html-to-markdown.util.js";
|
|
66
67
|
export * from "./Commons/apply-mask.util.js";
|