@dillingerstaffing/strand-svelte 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/strand-ui.css +2784 -223
- package/dist/index.js +1285 -1244
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/CodeBlock/CodeBlock.svelte +77 -1
- package/src/components/InstrumentViewport/InstrumentViewport.svelte +5 -0
- package/src/components/InstrumentViewport/InstrumentViewport.test.ts +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dillingerstaffing/strand-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Strand UI - Svelte component library built on the Strand Design Language",
|
|
5
5
|
"author": "Dillinger Staffing <engineering@dillingerstaffing.com> (https://dillingerstaffing.com)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"svelte": "^4.0.0 || ^5.0.0"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@dillingerstaffing/strand": "^0.
|
|
58
|
+
"@dillingerstaffing/strand": "^0.15.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
|
@@ -1,14 +1,90 @@
|
|
|
1
1
|
<!--! Strand Svelte | MIT License | dillingerstaffing.com -->
|
|
2
2
|
<script lang="ts">
|
|
3
|
+
import { onDestroy } from 'svelte'
|
|
4
|
+
|
|
3
5
|
/** The code content to display */
|
|
4
6
|
export let code: string
|
|
5
7
|
/** Optional language label (e.g. "html", "css", "bash") */
|
|
6
8
|
export let language: string | undefined = undefined
|
|
9
|
+
/**
|
|
10
|
+
* Render the one-click copy-to-clipboard button. Defaults to true so
|
|
11
|
+
* every CodeBlock is copyable out of the box; pass false to opt out
|
|
12
|
+
* for blocks that should not advertise a copy affordance.
|
|
13
|
+
*/
|
|
14
|
+
export let copyable = true
|
|
15
|
+
|
|
16
|
+
const COPIED_DURATION_MS = 1500
|
|
17
|
+
let copied = false
|
|
18
|
+
let timer: number | null = null
|
|
19
|
+
|
|
20
|
+
onDestroy(() => {
|
|
21
|
+
if (timer !== null) window.clearTimeout(timer)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
async function handleCopy() {
|
|
25
|
+
try {
|
|
26
|
+
if (navigator.clipboard?.writeText) {
|
|
27
|
+
await navigator.clipboard.writeText(code)
|
|
28
|
+
} else {
|
|
29
|
+
const ta = document.createElement('textarea')
|
|
30
|
+
ta.value = code
|
|
31
|
+
ta.setAttribute('readonly', '')
|
|
32
|
+
ta.style.position = 'absolute'
|
|
33
|
+
ta.style.left = '-9999px'
|
|
34
|
+
document.body.appendChild(ta)
|
|
35
|
+
ta.select()
|
|
36
|
+
document.execCommand('copy')
|
|
37
|
+
document.body.removeChild(ta)
|
|
38
|
+
}
|
|
39
|
+
copied = true
|
|
40
|
+
if (timer !== null) window.clearTimeout(timer)
|
|
41
|
+
timer = window.setTimeout(() => {
|
|
42
|
+
copied = false
|
|
43
|
+
}, COPIED_DURATION_MS)
|
|
44
|
+
} catch {
|
|
45
|
+
// Ignore copy failures.
|
|
46
|
+
}
|
|
47
|
+
}
|
|
7
48
|
</script>
|
|
8
49
|
|
|
9
|
-
<div class="strand-code-block" {...$$restProps}>
|
|
50
|
+
<div class="strand-code-block" data-strand-copy={copyable ? '' : undefined} {...$$restProps}>
|
|
10
51
|
{#if language}
|
|
11
52
|
<span class="strand-code-block__label">{language}</span>
|
|
12
53
|
{/if}
|
|
13
54
|
<pre class="strand-code-block__pre"><code>{code}</code></pre>
|
|
55
|
+
{#if copyable}
|
|
56
|
+
<button
|
|
57
|
+
type="button"
|
|
58
|
+
class="strand-code-block__copy {copied ? 'strand-code-block__copy--copied' : ''}"
|
|
59
|
+
aria-label={copied ? 'Copied' : 'Copy code to clipboard'}
|
|
60
|
+
on:click={handleCopy}
|
|
61
|
+
>
|
|
62
|
+
<svg
|
|
63
|
+
class="strand-code-block__copy-icon strand-code-block__copy-icon--clipboard"
|
|
64
|
+
viewBox="0 0 16 16"
|
|
65
|
+
fill="none"
|
|
66
|
+
stroke="currentColor"
|
|
67
|
+
stroke-width="1.75"
|
|
68
|
+
stroke-linecap="round"
|
|
69
|
+
stroke-linejoin="round"
|
|
70
|
+
aria-hidden="true"
|
|
71
|
+
focusable="false"
|
|
72
|
+
>
|
|
73
|
+
<path d="M6 3 V2 a1 1 0 0 1 1-1 h2 a1 1 0 0 1 1 1 v1 M5 3 h6 a1 1 0 0 1 1 1 v9 a1 1 0 0 1 -1 1 h-6 a1 1 0 0 1 -1 -1 v-9 a1 1 0 0 1 1 -1 z" />
|
|
74
|
+
</svg>
|
|
75
|
+
<svg
|
|
76
|
+
class="strand-code-block__copy-icon strand-code-block__copy-icon--check"
|
|
77
|
+
viewBox="0 0 16 16"
|
|
78
|
+
fill="none"
|
|
79
|
+
stroke="currentColor"
|
|
80
|
+
stroke-width="1.75"
|
|
81
|
+
stroke-linecap="round"
|
|
82
|
+
stroke-linejoin="round"
|
|
83
|
+
aria-hidden="true"
|
|
84
|
+
focusable="false"
|
|
85
|
+
>
|
|
86
|
+
<path d="M3 8 l3 3 l7 -7" />
|
|
87
|
+
</svg>
|
|
88
|
+
</button>
|
|
89
|
+
{/if}
|
|
14
90
|
</div>
|
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
<script lang="ts">
|
|
3
3
|
/** Show grid overlay lines */
|
|
4
4
|
export let grid: boolean = false
|
|
5
|
+
/** Render as page-filling instrument cabinet (DL Part 9.3 full-bleed mode).
|
|
6
|
+
* Requires the host page to apply `strand-body--instrument` to <body>
|
|
7
|
+
* so the dark surface reaches the screen edge. */
|
|
8
|
+
export let fullBleed: boolean = false
|
|
5
9
|
|
|
6
10
|
$: classes = [
|
|
7
11
|
'strand-instrument-viewport',
|
|
8
12
|
grid && 'strand-instrument-viewport--grid',
|
|
13
|
+
fullBleed && 'strand-instrument-viewport--full-bleed',
|
|
9
14
|
].filter(Boolean).join(' ')
|
|
10
15
|
</script>
|
|
11
16
|
|
|
@@ -22,4 +22,16 @@ describe('InstrumentViewport', () => {
|
|
|
22
22
|
const el = container.querySelector('.strand-instrument-viewport')
|
|
23
23
|
expect(el).toHaveClass('strand-instrument-viewport--grid')
|
|
24
24
|
})
|
|
25
|
+
|
|
26
|
+
it('does not apply full-bleed modifier by default', () => {
|
|
27
|
+
const { container } = render(InstrumentViewport)
|
|
28
|
+
const el = container.querySelector('.strand-instrument-viewport')
|
|
29
|
+
expect(el).not.toHaveClass('strand-instrument-viewport--full-bleed')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('applies full-bleed modifier when fullBleed prop is true', () => {
|
|
33
|
+
const { container } = render(InstrumentViewport, { props: { fullBleed: true } })
|
|
34
|
+
const el = container.querySelector('.strand-instrument-viewport')
|
|
35
|
+
expect(el).toHaveClass('strand-instrument-viewport--full-bleed')
|
|
36
|
+
})
|
|
25
37
|
})
|