From a9d97017250262de1ccae9107e074181bfc53c5f Mon Sep 17 00:00:00 2001 From: Hugo ATTAL Date: Sun, 9 Oct 2022 21:37:35 +0200 Subject: [PATCH] feat: add JSON control (#319) Co-authored-by: Guillaume Chau Related to #30 --- .../vue3/src/components/Controls.story.vue | 5 + .../panel/ControlsComponentPropItem.vue | 41 +---- packages/histoire-app/src/app/util/dark.ts | 17 ++ packages/histoire-app/src/shim.d.ts | 9 ++ packages/histoire-controls/package.json | 7 + .../src/components/HstWrapper.vue | 9 +- .../__snapshots__/HstCheckbox.test.ts.snap | 8 +- .../src/components/json/HstJson.story.vue | 41 +++++ .../src/components/json/HstJson.vue | 148 ++++++++++++++++++ packages/histoire-controls/src/end.d.ts | 8 + packages/histoire-controls/src/index.ts | 3 + packages/histoire-controls/src/utils.ts | 12 ++ packages/histoire-plugin-svelte/src/index.ts | 4 + packages/histoire-shared/src/state.ts | 8 +- pnpm-lock.yaml | 105 +++++++++++++ 15 files changed, 374 insertions(+), 51 deletions(-) create mode 100644 packages/histoire-controls/src/components/json/HstJson.story.vue create mode 100644 packages/histoire-controls/src/components/json/HstJson.vue create mode 100644 packages/histoire-controls/src/end.d.ts create mode 100644 packages/histoire-controls/src/utils.ts diff --git a/examples/vue3/src/components/Controls.story.vue b/examples/vue3/src/components/Controls.story.vue index cb57657d..65474fc6 100644 --- a/examples/vue3/src/components/Controls.story.vue +++ b/examples/vue3/src/components/Controls.story.vue @@ -19,6 +19,7 @@ function initState () { longText: 'Longer text...', select: 'crash-bandicoot', radio: 'metal-gear', + object: { foo: 'bar' }, } } @@ -67,6 +68,10 @@ function initState () { title="HstRadio" :options="radioOptions" /> + diff --git a/packages/histoire-app/src/app/components/panel/ControlsComponentPropItem.vue b/packages/histoire-app/src/app/components/panel/ControlsComponentPropItem.vue index 660dd4e9..9889b6fc 100644 --- a/packages/histoire-app/src/app/components/panel/ControlsComponentPropItem.vue +++ b/packages/histoire-app/src/app/components/panel/ControlsComponentPropItem.vue @@ -1,13 +1,8 @@ + + diff --git a/packages/histoire-controls/src/components/json/HstJson.vue b/packages/histoire-controls/src/components/json/HstJson.vue new file mode 100644 index 00000000..915c2220 --- /dev/null +++ b/packages/histoire-controls/src/components/json/HstJson.vue @@ -0,0 +1,148 @@ + + + + + + + diff --git a/packages/histoire-controls/src/end.d.ts b/packages/histoire-controls/src/end.d.ts new file mode 100644 index 00000000..e134bef1 --- /dev/null +++ b/packages/histoire-controls/src/end.d.ts @@ -0,0 +1,8 @@ +import type { Ref } from '@histoire/vendors/vue' + +global { + interface Window { + __hst_controls_dark: Ref[] + __hst_controls_dark_ready: () => void + } +} diff --git a/packages/histoire-controls/src/index.ts b/packages/histoire-controls/src/index.ts index d23a656e..89ab6b47 100644 --- a/packages/histoire-controls/src/index.ts +++ b/packages/histoire-controls/src/index.ts @@ -12,6 +12,7 @@ import HstTokenListVue from './components/design-tokens/HstTokenList.vue' import HstTokenGridVue from './components/design-tokens/HstTokenGrid.vue' import HstCopyIconVue from './components/HstCopyIcon.vue' import HstRadioVue from './components/radio/HstRadio.vue' +import HstJsonVue from './components/json/HstJson.vue' export const HstButton = HstButtonVue export const HstButtonGroup = HstButtonGroupVue @@ -27,6 +28,7 @@ export const HstTokenList = HstTokenListVue export const HstTokenGrid = HstTokenGridVue export const HstCopyIcon = HstCopyIconVue export const HstRadio = HstRadioVue +export const HstJson = HstJsonVue export const components = { HstButton, @@ -43,6 +45,7 @@ export const components = { HstTokenGrid, HstCopyIcon, HstRadio, + HstJson, } export * from './types' diff --git a/packages/histoire-controls/src/utils.ts b/packages/histoire-controls/src/utils.ts new file mode 100644 index 00000000..49d2f483 --- /dev/null +++ b/packages/histoire-controls/src/utils.ts @@ -0,0 +1,12 @@ +import { ref } from 'vue' + +export const isDark = ref(false) + +if (!window.__hst_controls_dark) { + window.__hst_controls_dark = [] +} + +// There could be multiple instances of the controls lib (in the controls book https://controls.histoire.dev) +window.__hst_controls_dark.push(isDark) + +window.__hst_controls_dark_ready?.() diff --git a/packages/histoire-plugin-svelte/src/index.ts b/packages/histoire-plugin-svelte/src/index.ts index 3f5c3af2..2783a6c4 100644 --- a/packages/histoire-plugin-svelte/src/index.ts +++ b/packages/histoire-plugin-svelte/src/index.ts @@ -100,6 +100,10 @@ export interface Hst { options: HstControlOption[] title?: string }> + Json: typeof SvelteComponentTyped<{ + value: unknown + title: string + }> Shades: typeof SvelteComponentTyped<{ shades: Record getName?: (key: string, color: string) => string diff --git a/packages/histoire-shared/src/state.ts b/packages/histoire-shared/src/state.ts index ae4b6dac..db4db05e 100644 --- a/packages/histoire-shared/src/state.ts +++ b/packages/histoire-shared/src/state.ts @@ -22,12 +22,8 @@ export function omit (data, keys: string[]) { return copy } -export function applyState (target: any, state: any, override = false) { +export function applyState (target: any, state: any) { for (const key in state) { - if (!override && target[key] && !key.startsWith('_h') && typeof target[key] === 'object' && !Array.isArray(target[key])) { - Object.assign(target[key], state[key]) - } else { - target[key] = state[key] - } + target[key] = state[key] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c001d3c..b53f9ce9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -380,6 +380,13 @@ importers: packages/histoire-controls: specifiers: + '@codemirror/commands': ^6.1.1 + '@codemirror/lang-json': ^6.0.0 + '@codemirror/language': ^6.2.1 + '@codemirror/lint': ^6.0.0 + '@codemirror/state': ^6.1.2 + '@codemirror/theme-one-dark': ^6.1.0 + '@codemirror/view': ^6.3.0 '@histoire/vendors': ^0.11.2 '@peeky/server': ^0.14.0 '@peeky/test': ^0.14.1 @@ -398,6 +405,13 @@ importers: vue: ^3.2.31 vue-tsc: ^0.35.2 dependencies: + '@codemirror/commands': 6.1.1 + '@codemirror/lang-json': 6.0.0 + '@codemirror/language': 6.2.1 + '@codemirror/lint': 6.0.0 + '@codemirror/state': 6.1.2 + '@codemirror/theme-one-dark': 6.1.0 + '@codemirror/view': 6.3.0 '@histoire/vendors': link:../histoire-vendors devDependencies: '@peeky/server': 0.14.0 @@ -1194,6 +1208,62 @@ packages: resolution: {integrity: sha512-gaBUSaKS65mN3iKZEgichbXYEmAa/pXkc5Gbt+1BptYphdGkj09ggdsiE4w8g0F/uI1g36QaTKrzVnBAWMipvQ==} dev: true + /@codemirror/commands/6.1.1: + resolution: {integrity: sha512-ibDohwkk7vyu3VsnZNlQhwk0OETBtlkYV+6AHfn5Zgq0sxa+yGVX+apwtC3M4wh6AH7yU5si/NysoECs5EGS3Q==} + dependencies: + '@codemirror/language': 6.2.1 + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.3.0 + '@lezer/common': 1.0.1 + dev: false + + /@codemirror/lang-json/6.0.0: + resolution: {integrity: sha512-DvTcYTKLmg2viADXlTdufrT334M9jowe1qO02W28nvm+nejcvhM5vot5mE8/kPrxYw/HJHhwu1z2PyBpnMLCNQ==} + dependencies: + '@codemirror/language': 6.2.1 + '@lezer/json': 1.0.0 + dev: false + + /@codemirror/language/6.2.1: + resolution: {integrity: sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==} + dependencies: + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.3.0 + '@lezer/common': 1.0.1 + '@lezer/highlight': 1.1.1 + '@lezer/lr': 1.2.3 + style-mod: 4.0.0 + dev: false + + /@codemirror/lint/6.0.0: + resolution: {integrity: sha512-nUUXcJW1Xp54kNs+a1ToPLK8MadO0rMTnJB8Zk4Z8gBdrN0kqV7uvUraU/T2yqg+grDNR38Vmy/MrhQN/RgwiA==} + dependencies: + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.3.0 + crelt: 1.0.5 + dev: false + + /@codemirror/state/6.1.2: + resolution: {integrity: sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==} + dev: false + + /@codemirror/theme-one-dark/6.1.0: + resolution: {integrity: sha512-AiTHtFRu8+vWT9wWUWDM+cog6ZwgivJogB1Tm/g40NIpLwph7AnmxrSzWfvJN5fBVufsuwBxecQCNmdcR5D7Aw==} + dependencies: + '@codemirror/language': 6.2.1 + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.3.0 + '@lezer/highlight': 1.1.1 + dev: false + + /@codemirror/view/6.3.0: + resolution: {integrity: sha512-jMN9OGKmzRPJ+kksfMrB5e/A9heQncirHsz8XNBpgEbYONCk5tWHMKVWKTNwznkUGD5mnigXI1i5YIcWpscSPg==} + dependencies: + '@codemirror/state': 6.1.2 + style-mod: 4.0.0 + w3c-keyname: 2.2.6 + dev: false + /@colors/colors/1.5.0: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -1604,6 +1674,29 @@ packages: - supports-color dev: true + /@lezer/common/1.0.1: + resolution: {integrity: sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==} + dev: false + + /@lezer/highlight/1.1.1: + resolution: {integrity: sha512-duv9D23O9ghEDnnUDmxu+L8pJy4nYo4AbCOHIudUhscrLSazqeJeK1V50EU6ZufWF1zv0KJwu/frFRyZWXxHBQ==} + dependencies: + '@lezer/common': 1.0.1 + dev: false + + /@lezer/json/1.0.0: + resolution: {integrity: sha512-zbAuUY09RBzCoCA3lJ1+ypKw5WSNvLqGMtasdW6HvVOqZoCpPr8eWrsGnOVWGKGn8Rh21FnrKRVlJXrGAVUqRw==} + dependencies: + '@lezer/highlight': 1.1.1 + '@lezer/lr': 1.2.3 + dev: false + + /@lezer/lr/1.2.3: + resolution: {integrity: sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==} + dependencies: + '@lezer/common': 1.0.1 + dev: false + /@mapbox/node-pre-gyp/1.0.10: resolution: {integrity: sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==} hasBin: true @@ -4475,6 +4568,10 @@ packages: /create-require/1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + /crelt/1.0.5: + resolution: {integrity: sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==} + dev: false + /cross-fetch/3.1.5: resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} dependencies: @@ -10439,6 +10536,10 @@ packages: dependencies: acorn: 8.8.0 + /style-mod/4.0.0: + resolution: {integrity: sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==} + dev: false + /stylehacks/5.1.0_postcss@8.4.17: resolution: {integrity: sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==} engines: {node: ^10 || ^12 || >=14.0} @@ -11704,6 +11805,10 @@ packages: vite-plugin-vuetify: 1.0.0-alpha.12_tacspt2dmukucclm75di65rrdy vue: 3.2.40 + /w3c-keyname/2.2.6: + resolution: {integrity: sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==} + dev: false + /wait-on/6.0.0_debug@4.3.2: resolution: {integrity: sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==} engines: {node: '>=10.0.0'}