@histoire/controls 0.11.1 → 0.11.3

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.
@@ -404,6 +404,10 @@
404
404
  height:5rem
405
405
  }
406
406
 
407
+ .htw-h-48{
408
+ height:12rem
409
+ }
410
+
407
411
  .htw-h-\[27px\]{
408
412
  height:27px
409
413
  }
@@ -416,6 +420,10 @@
416
420
  height:0.75rem
417
421
  }
418
422
 
423
+ .htw-min-h-32{
424
+ min-height:8rem
425
+ }
426
+
419
427
  .htw-min-h-\[26px\]{
420
428
  min-height:26px
421
429
  }
@@ -448,6 +456,10 @@
448
456
  width:0.75rem
449
457
  }
450
458
 
459
+ .htw-max-w-full{
460
+ max-width:100%
461
+ }
462
+
451
463
  .htw-flex-1{
452
464
  flex:1 1 0%
453
465
  }
@@ -542,6 +554,10 @@
542
554
  gap:1rem
543
555
  }
544
556
 
557
+ .htw-overflow-auto{
558
+ overflow:auto
559
+ }
560
+
545
561
  .htw-overflow-hidden{
546
562
  overflow:hidden
547
563
  }
@@ -733,6 +749,11 @@
733
749
  color:rgb(255 255 255 / var(--tw-text-opacity))
734
750
  }
735
751
 
752
+ .htw-text-orange-500{
753
+ --tw-text-opacity:1;
754
+ color:rgb(249 115 22 / var(--tw-text-opacity))
755
+ }
756
+
736
757
  .htw-text-inherit{
737
758
  color:inherit
738
759
  }
@@ -806,6 +827,11 @@ body {
806
827
  }
807
828
  }
808
829
 
830
+ .focus-within\:htw-border-primary-500:focus-within{
831
+ --tw-border-opacity:1;
832
+ border-color:rgb(16 185 129 / var(--tw-border-opacity))
833
+ }
834
+
809
835
  .hover\:htw-border-primary-500:hover{
810
836
  --tw-border-opacity:1;
811
837
  border-color:rgb(16 185 129 / var(--tw-border-opacity))
@@ -892,6 +918,11 @@ body {
892
918
  color:rgb(0 0 0 / var(--tw-text-opacity))
893
919
  }
894
920
 
921
+ .htw-dark .dark\:focus-within\:htw-border-primary-500:focus-within{
922
+ --tw-border-opacity:1;
923
+ border-color:rgb(16 185 129 / var(--tw-border-opacity))
924
+ }
925
+
895
926
  .htw-dark .dark\:hover\:htw-border-primary-500:hover{
896
927
  --tw-border-opacity:1;
897
928
  border-color:rgb(16 185 129 / var(--tw-border-opacity))
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .htw-range-input::-webkit-slider-thumb{height:.75rem;width:.75rem;-webkit-appearance:none;appearance:none;border-radius:9999px;border-width:1px;border-style:solid;border-color:#00000040;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.htw-dark .htw-range-input::-webkit-slider-thumb{border-color:#ffffff40;--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity))}.htw-range-input:hover::-webkit-slider-thumb{--tw-border-opacity: 1 !important;border-color:rgb(16 185 129 / var(--tw-border-opacity))!important;--tw-bg-opacity: 1 !important;background-color:rgb(16 185 129 / var(--tw-bg-opacity))!important}.htw-range-input::-moz-range-thumb{height:.75rem;width:.75rem;-moz-appearance:none;appearance:none;border-radius:9999px;border-width:1px;border-style:solid;border-color:#00000040;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.htw-dark .htw-range-input::-moz-range-thumb{border-color:#ffffff40;--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity))}.htw-range-input:hover::-moz-range-thumb{--tw-border-opacity: 1 !important;border-color:rgb(16 185 129 / var(--tw-border-opacity))!important;--tw-bg-opacity: 1 !important;background-color:rgb(16 185 129 / var(--tw-bg-opacity))!important}.v-popper{line-height:0}.htw-dark .v-popper--theme-dropdown .v-popper__inner{--tw-border-opacity: 1;border-color:rgb(31 31 33 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity))}.htw-dark .v-popper--theme-dropdown .v-popper__arrow-inner{--tw-border-opacity: 1;border-color:rgb(63 63 70 / var(--tw-border-opacity))}.htw-dark .v-popper--theme-dropdown .v-popper__arrow-outer{--tw-border-opacity: 1;border-color:rgb(31 31 33 / var(--tw-border-opacity))}.v-popper--theme-dropdown.v-popper__popper--show-from .v-popper__wrapper{transform:scale(.75)}.v-popper--theme-dropdown.v-popper__popper--show-to .v-popper__wrapper{transform:none;transition:transform .15s cubic-bezier(0,1,.5,1)}.v-popper__popper:focus-visible{outline:none}.htw-bind-col-size{grid-template-columns:repeat(auto-fill,minmax(var(--histoire-col-size),1fr))}
1
+ .htw-range-input::-webkit-slider-thumb{height:.75rem;width:.75rem;-webkit-appearance:none;appearance:none;border-radius:9999px;border-width:1px;border-style:solid;border-color:#00000040;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.htw-dark .htw-range-input::-webkit-slider-thumb{border-color:#ffffff40;--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity))}.htw-range-input:hover::-webkit-slider-thumb{--tw-border-opacity: 1 !important;border-color:rgb(16 185 129 / var(--tw-border-opacity))!important;--tw-bg-opacity: 1 !important;background-color:rgb(16 185 129 / var(--tw-bg-opacity))!important}.htw-range-input::-moz-range-thumb{height:.75rem;width:.75rem;-moz-appearance:none;appearance:none;border-radius:9999px;border-width:1px;border-style:solid;border-color:#00000040;--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.htw-dark .htw-range-input::-moz-range-thumb{border-color:#ffffff40;--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity))}.htw-range-input:hover::-moz-range-thumb{--tw-border-opacity: 1 !important;border-color:rgb(16 185 129 / var(--tw-border-opacity))!important;--tw-bg-opacity: 1 !important;background-color:rgb(16 185 129 / var(--tw-bg-opacity))!important}.v-popper{line-height:0}.htw-dark .v-popper--theme-dropdown .v-popper__inner{--tw-border-opacity: 1;border-color:rgb(31 31 33 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity))}.htw-dark .v-popper--theme-dropdown .v-popper__arrow-inner{--tw-border-opacity: 1;border-color:rgb(63 63 70 / var(--tw-border-opacity))}.htw-dark .v-popper--theme-dropdown .v-popper__arrow-outer{--tw-border-opacity: 1;border-color:rgb(31 31 33 / var(--tw-border-opacity))}.v-popper--theme-dropdown.v-popper__popper--show-from .v-popper__wrapper{transform:scale(.75)}.v-popper--theme-dropdown.v-popper__popper--show-to .v-popper__wrapper{transform:none;transition:transform .15s cubic-bezier(0,1,.5,1)}.v-popper__popper:focus-visible{outline:none}.htw-bind-col-size{grid-template-columns:repeat(auto-fill,minmax(var(--histoire-col-size),1fr))}.__histoire-json-code[data-v-35a6e314] .cm-editor{height:100%;min-width:280px}
@@ -0,0 +1 @@
1
+ export declare const isDark: import("vue").Ref<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@histoire/controls",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "description": "Prebuilt controls components",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -31,7 +31,14 @@
31
31
  "*.vue"
32
32
  ],
33
33
  "dependencies": {
34
- "@histoire/vendors": "^0.11.1"
34
+ "@codemirror/commands": "^6.1.1",
35
+ "@codemirror/lang-json": "^6.0.0",
36
+ "@codemirror/language": "^6.2.1",
37
+ "@codemirror/lint": "^6.0.0",
38
+ "@codemirror/state": "^6.1.2",
39
+ "@codemirror/theme-one-dark": "^6.1.0",
40
+ "@codemirror/view": "^6.3.0",
41
+ "@histoire/vendors": "^0.11.3"
35
42
  },
36
43
  "devDependencies": {
37
44
  "@peeky/server": "^0.14.0",
@@ -5,13 +5,14 @@ export default {
5
5
  </script>
6
6
 
7
7
  <script lang="ts" setup>
8
- import { withDefaults, computed } from 'vue'
8
+ import { withDefaults } from 'vue'
9
9
  import { VTooltip as vTooltip } from 'floating-vue'
10
10
 
11
- const props = withDefaults(defineProps<{
11
+ withDefaults(defineProps<{
12
12
  title?: string
13
13
  tag?: string
14
14
  }>(), {
15
+ title: undefined,
15
16
  tag: 'label',
16
17
  })
17
18
 
@@ -32,8 +33,8 @@ const props = withDefaults(defineProps<{
32
33
  >
33
34
  {{ title }}
34
35
  </span>
35
- <span class="htw-grow htw-flex htw-items-center htw-gap-1">
36
- <span class="htw-block htw-grow">
36
+ <span class="htw-grow htw-max-w-full htw-flex htw-items-center htw-gap-1">
37
+ <span class="htw-block htw-grow htw-max-w-full">
37
38
  <slot />
38
39
  </span>
39
40
  <slot name="actions" />
@@ -9,8 +9,8 @@ exports[`HstCheckbox toggle to checked 1`] = `
9
9
  <span class="htw-w-28 htw-whitespace-nowrap htw-text-ellipsis htw-overflow-hidden htw-shrink-0 v-popper--has-tooltip">
10
10
  Label
11
11
  </span>
12
- <span class="htw-grow htw-flex htw-items-center htw-gap-1">
13
- <span class="htw-block htw-grow">
12
+ <span class="htw-grow htw-max-w-full htw-flex htw-items-center htw-gap-1">
13
+ <span class="htw-block htw-grow htw-max-w-full">
14
14
  <div class="htw-group htw-text-white htw-w-[16px] htw-h-[16px] htw-relative">
15
15
  <div class="htw-border htw-border-solid group-active:htw-bg-gray-500/20 htw-rounded-sm htw-box-border htw-absolute htw-inset-0 htw-transition-border htw-duration-150 htw-ease-out group-hover:htw-border-primary-500 group-hover:dark:htw-border-primary-500 htw-border-black/25 dark:htw-border-white/25 htw-delay-150">
16
16
  </div>
@@ -44,8 +44,8 @@ exports[`HstCheckbox toggle to unchecked 1`] = `
44
44
  <span class="htw-w-28 htw-whitespace-nowrap htw-text-ellipsis htw-overflow-hidden htw-shrink-0 v-popper--has-tooltip">
45
45
  Label
46
46
  </span>
47
- <span class="htw-grow htw-flex htw-items-center htw-gap-1">
48
- <span class="htw-block htw-grow">
47
+ <span class="htw-grow htw-max-w-full htw-flex htw-items-center htw-gap-1">
48
+ <span class="htw-block htw-grow htw-max-w-full">
49
49
  <div class="htw-group htw-text-white htw-w-[16px] htw-h-[16px] htw-relative">
50
50
  <div class="htw-border htw-border-solid group-active:htw-bg-gray-500/20 htw-rounded-sm htw-box-border htw-absolute htw-inset-0 htw-transition-border htw-duration-150 htw-ease-out group-hover:htw-border-primary-500 group-hover:dark:htw-border-primary-500 htw-border-primary-500 htw-border-8">
51
51
  </div>
@@ -0,0 +1,41 @@
1
+ <script lang="ts" setup>
2
+ import HstJson from './HstJson.vue'
3
+
4
+ function initState () {
5
+ return {
6
+ film: {
7
+ year: 2017,
8
+ title: 'Blade Runner 2049',
9
+ actors: ['Ryan Gosling', 'Harrison Ford', 'Ana de Armas', 'Sylvia Hoeks'],
10
+ },
11
+ }
12
+ }
13
+ </script>
14
+
15
+ <template>
16
+ <Story
17
+ title="HstJson"
18
+ group="controls"
19
+ :layout="{ type: 'single', iframe: false }"
20
+ >
21
+ <Variant
22
+ title="default"
23
+ :init-state="initState"
24
+ >
25
+ <template #default="{ state }">
26
+ <HstJson
27
+ v-model="state.film"
28
+ title="Textarea"
29
+ />
30
+ <pre>{{ state.film }}</pre>
31
+ </template>
32
+
33
+ <template #controls="{ state }">
34
+ <HstJson
35
+ v-model="state.film"
36
+ title="Text"
37
+ />
38
+ </template>
39
+ </Variant>
40
+ </Story>
41
+ </template>
@@ -0,0 +1,148 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'HstJson',
4
+ inheritAttrs: false,
5
+ }
6
+ </script>
7
+
8
+ <script lang="ts" setup>
9
+ import { ref, onMounted, watch, watchEffect } from 'vue'
10
+ import { Icon } from '@iconify/vue'
11
+ import HstWrapper from '../HstWrapper.vue'
12
+ import { VTooltip as vTooltip } from 'floating-vue'
13
+ import { Compartment } from '@codemirror/state'
14
+ import {
15
+ EditorView,
16
+ keymap,
17
+ highlightActiveLineGutter,
18
+ highlightActiveLine,
19
+ highlightSpecialChars,
20
+ ViewUpdate,
21
+ } from '@codemirror/view'
22
+ import { defaultKeymap } from '@codemirror/commands'
23
+ import { json } from '@codemirror/lang-json'
24
+ import {
25
+ defaultHighlightStyle,
26
+ syntaxHighlighting,
27
+ indentOnInput,
28
+ bracketMatching,
29
+ foldGutter,
30
+ foldKeymap,
31
+ } from '@codemirror/language'
32
+ import { lintKeymap } from '@codemirror/lint'
33
+ import { oneDarkTheme, oneDarkHighlightStyle } from '@codemirror/theme-one-dark'
34
+ import { isDark } from '../../utils'
35
+
36
+ const props = defineProps<{
37
+ title?: string
38
+ modelValue: unknown
39
+ }>()
40
+
41
+ const emits = defineEmits({
42
+ 'update:modelValue': (newValue: unknown) => true,
43
+ })
44
+
45
+ let editorView: EditorView
46
+ const internalValue = ref('')
47
+ const invalidValue = ref(false)
48
+ const editorElement = ref<HTMLInputElement>()
49
+
50
+ const themes = {
51
+ light: [EditorView.baseTheme({}), syntaxHighlighting(defaultHighlightStyle)],
52
+ dark: [oneDarkTheme, syntaxHighlighting(oneDarkHighlightStyle)],
53
+ }
54
+
55
+ const themeConfig = new Compartment()
56
+
57
+ const extensions = [
58
+ highlightActiveLineGutter(),
59
+ highlightActiveLine(),
60
+ highlightSpecialChars(),
61
+ json(),
62
+ bracketMatching(),
63
+ indentOnInput(),
64
+ foldGutter(),
65
+ keymap.of([
66
+ ...defaultKeymap,
67
+ ...foldKeymap,
68
+ ...lintKeymap,
69
+ ]),
70
+ EditorView.updateListener.of((viewUpdate: ViewUpdate) => {
71
+ internalValue.value = viewUpdate.view.state.doc.toString()
72
+ }),
73
+ themeConfig.of(themes.light),
74
+ ]
75
+
76
+ onMounted(() => {
77
+ editorView = new EditorView({
78
+ doc: JSON.stringify(props.modelValue, null, 2),
79
+ extensions,
80
+ parent: editorElement.value,
81
+ })
82
+
83
+ watchEffect(() => {
84
+ editorView.dispatch({
85
+ effects: [
86
+ themeConfig.reconfigure(themes[isDark.value ? 'dark' : 'light']),
87
+ ],
88
+ })
89
+ })
90
+ })
91
+
92
+ watch(() => props.modelValue, () => {
93
+ let sameDocument
94
+
95
+ try {
96
+ sameDocument = (JSON.stringify(JSON.parse(internalValue.value)) === JSON.stringify(props.modelValue))
97
+ } catch (e) {
98
+ sameDocument = false
99
+ }
100
+
101
+ if (!sameDocument) {
102
+ editorView.dispatch({ changes: [{ from: 0, to: editorView.state.doc.length, insert: JSON.stringify(props.modelValue, null, 2) }] })
103
+ }
104
+ }, { deep: true })
105
+
106
+ watch(() => internalValue.value, () => {
107
+ invalidValue.value = false
108
+ try {
109
+ emits('update:modelValue', JSON.parse(internalValue.value))
110
+ } catch (e) {
111
+ invalidValue.value = true
112
+ }
113
+ })
114
+
115
+ </script>
116
+
117
+ <template>
118
+ <HstWrapper
119
+ :title="title"
120
+ class="htw-cursor-text"
121
+ :class="$attrs.class"
122
+ :style="$attrs.style"
123
+ >
124
+ <div
125
+ ref="editorElement"
126
+ class="__histoire-json-code htw-w-full htw-border htw-border-solid htw-border-black/25 dark:htw-border-white/25 focus-within:htw-border-primary-500 dark:focus-within:htw-border-primary-500 htw-rounded-sm htw-box-border htw-overflow-auto htw-resize-y htw-min-h-32 htw-h-48 htw-relative"
127
+ v-bind="{ ...$attrs, class: null, style: null }"
128
+ />
129
+
130
+ <template #actions>
131
+ <Icon
132
+ v-if="invalidValue"
133
+ v-tooltip="'JSON error'"
134
+ icon="carbon:warning-alt"
135
+ class="htw-text-orange-500"
136
+ />
137
+
138
+ <slot name="actions" />
139
+ </template>
140
+ </HstWrapper>
141
+ </template>
142
+
143
+ <style scoped>
144
+ .__histoire-json-code :deep(.cm-editor) {
145
+ height: 100%;
146
+ min-width: 280px;
147
+ }
148
+ </style>
package/src/end.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { Ref } from '@histoire/vendors/vue'
2
+
3
+ global {
4
+ interface Window {
5
+ __hst_controls_dark: Ref<boolean>[]
6
+ __hst_controls_dark_ready: () => void
7
+ }
8
+ }
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ import HstTokenListVue from './components/design-tokens/HstTokenList.vue'
12
12
  import HstTokenGridVue from './components/design-tokens/HstTokenGrid.vue'
13
13
  import HstCopyIconVue from './components/HstCopyIcon.vue'
14
14
  import HstRadioVue from './components/radio/HstRadio.vue'
15
+ import HstJsonVue from './components/json/HstJson.vue'
15
16
 
16
17
  export const HstButton = HstButtonVue
17
18
  export const HstButtonGroup = HstButtonGroupVue
@@ -27,6 +28,7 @@ export const HstTokenList = HstTokenListVue
27
28
  export const HstTokenGrid = HstTokenGridVue
28
29
  export const HstCopyIcon = HstCopyIconVue
29
30
  export const HstRadio = HstRadioVue
31
+ export const HstJson = HstJsonVue
30
32
 
31
33
  export const components = {
32
34
  HstButton,
@@ -43,6 +45,7 @@ export const components = {
43
45
  HstTokenGrid,
44
46
  HstCopyIcon,
45
47
  HstRadio,
48
+ HstJson,
46
49
  }
47
50
 
48
51
  export * from './types'
package/src/utils.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { ref } from 'vue'
2
+
3
+ export const isDark = ref(false)
4
+
5
+ if (!window.__hst_controls_dark) {
6
+ window.__hst_controls_dark = []
7
+ }
8
+
9
+ // There could be multiple instances of the controls lib (in the controls book https://controls.histoire.dev)
10
+ window.__hst_controls_dark.push(isDark)
11
+
12
+ window.__hst_controls_dark_ready?.()