From 2ae1d157d9a0394b37fc155730d3f34da453ac43 Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Mon, 4 Mar 2024 09:15:31 +0300 Subject: [PATCH 01/12] feat: add `mods` into component panel --- packages/devtools-core/components-lock.json | 260 +++++++++++++++++- .../b-components-panel/interface.ts | 2 +- .../b-components-panel/modules/helpers.ts | 37 ++- .../src/pages/p-components/p-components.ts | 14 +- 4 files changed, 289 insertions(+), 24 deletions(-) diff --git a/packages/devtools-core/components-lock.json b/packages/devtools-core/components-lock.json index e2d34c6..89719d6 100644 --- a/packages/devtools-core/components-lock.json +++ b/packages/devtools-core/components-lock.json @@ -1,5 +1,5 @@ { - "hash": "259be7cc81f597f84b81f64779b6f77724b053b4c5f24d7cd19c56168c2aad40", + "hash": "b68f8922f12b1ef2d5f3b9d117610914aaffcfa437c5d518b0f27cf1d80f1750", "data": { "%data": "%data:Map", "%data:Map": [ @@ -111,6 +111,196 @@ "etpl": null } ], + [ + "b-components-actions", + { + "index": "src/features/components/b-components-actions/index.js", + "declaration": { + "name": "b-components-actions", + "parent": "i-block", + "dependencies": [ + "b-icon-button", + "b-button", + "b-window" + ], + "libs": [] + }, + "name": "b-components-actions", + "parent": "i-block", + "dependencies": [ + "b-icon-button", + "b-button", + "b-window" + ], + "libs": [], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "type": "block", + "mixin": false, + "logic": "src/features/components/b-components-actions/b-components-actions.ts", + "styles": [ + "src/features/components/b-components-actions/b-components-actions.styl" + ], + "tpl": "src/features/components/b-components-actions/b-components-actions.ss", + "etpl": null + } + ], + [ + "b-components-panel", + { + "index": "src/features/components/b-components-panel/index.js", + "declaration": { + "name": "b-components-panel", + "parent": "i-block", + "dependencies": [ + "b-components-panel-item", + "b-tree", + "b-checkbox" + ], + "libs": [] + }, + "name": "b-components-panel", + "parent": "i-block", + "dependencies": [ + "b-components-panel-item", + "b-tree", + "b-checkbox" + ], + "libs": [], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "type": "block", + "mixin": false, + "logic": "src/features/components/b-components-panel/b-components-panel.ts", + "styles": [ + "src/features/components/b-components-panel/b-components-panel.styl" + ], + "tpl": "src/features/components/b-components-panel/b-components-panel.ss", + "etpl": null + } + ], + [ + "b-components-panel-item", + { + "index": "src/features/components/b-components-panel/modules/b-components-panel-item/index.js", + "declaration": { + "name": "b-components-panel-item", + "parent": "i-block", + "dependencies": [], + "libs": [] + }, + "name": "b-components-panel-item", + "parent": "i-block", + "dependencies": [], + "libs": [], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "type": "block", + "mixin": false, + "logic": "src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts", + "styles": [], + "tpl": "src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss", + "etpl": null + } + ], + [ + "b-components-tree", + { + "index": "src/features/components/b-components-tree/index.js", + "declaration": { + "name": "b-components-tree", + "parent": "i-block", + "dependencies": [ + "b-components-tree-item", + "b-tree", + "b-input" + ], + "libs": [] + }, + "name": "b-components-tree", + "parent": "i-block", + "dependencies": [ + "b-components-tree-item", + "b-tree", + "b-input" + ], + "libs": [], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "type": "block", + "mixin": false, + "logic": "src/features/components/b-components-tree/b-components-tree.ts", + "styles": [ + "src/features/components/b-components-tree/b-components-tree.styl" + ], + "tpl": "src/features/components/b-components-tree/b-components-tree.ss", + "etpl": null + } + ], + [ + "b-components-tree-item", + { + "index": "src/features/components/b-components-tree/modules/b-components-tree-item/index.js", + "declaration": { + "name": "b-components-tree-item", + "parent": "i-block", + "dependencies": [], + "libs": [ + "components/directives/highlight" + ] + }, + "name": "b-components-tree-item", + "parent": "i-block", + "dependencies": [], + "libs": [ + "components/directives/highlight" + ], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [ + "components/directives/highlight" + ] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [ + "components/directives/highlight" + ] + }, + "type": "block", + "mixin": false, + "logic": "src/features/components/b-components-tree/modules/b-components-tree-item/b-components-tree-item.ts", + "styles": [ + "src/features/components/b-components-tree/modules/b-components-tree-item/b-components-tree-item.styl" + ], + "tpl": "src/features/components/b-components-tree/modules/b-components-tree-item/b-components-tree-item.ss", + "etpl": null + } + ], [ "b-dummy", { @@ -594,19 +784,21 @@ [ "b-header", { - "index": "src/widgets/b-header/index.js", + "index": "src/components/widgets/b-header/index.js", "declaration": { "name": "b-header", "parent": "i-block", "dependencies": [ - "b-button" + "b-button", + "b-components-actions" ], "libs": [] }, "name": "b-header", "parent": "i-block", "dependencies": [ - "b-button" + "b-button", + "b-components-actions" ], "libs": [], "resolvedLibs": { @@ -619,11 +811,11 @@ }, "type": "block", "mixin": false, - "logic": "src/widgets/b-header/b-header.ts", + "logic": "src/components/widgets/b-header/b-header.ts", "styles": [ - "src/widgets/b-header/b-header.styl" + "src/components/widgets/b-header/b-header.styl" ], - "tpl": "src/widgets/b-header/b-header.ss", + "tpl": "src/components/widgets/b-header/b-header.ss", "etpl": null } ], @@ -1417,9 +1609,9 @@ }, "type": "block", "mixin": false, - "logic": "src/components/base/b-tree/b-tree.ts", + "logic": "node_modules/@v4fire/client/src/components/base/b-tree/b-tree.ts", "styles": [ - "node_modules/@v4fire/client/src/components/base/b-tree/b-tree.styl" + "src/components/base/b-tree/b-tree.styl" ], "tpl": "node_modules/@v4fire/client/src/components/base/b-tree/b-tree.ss", "etpl": null @@ -2093,6 +2285,36 @@ "etpl": null } ], + [ + "i-search", + { + "index": "src/components/traits/i-search/index.js", + "declaration": { + "name": "i-search", + "parent": null, + "dependencies": [], + "libs": [] + }, + "name": "i-search", + "parent": null, + "dependencies": [], + "libs": [], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "type": "interface", + "mixin": false, + "logic": "src/components/traits/i-search/i-search.ts", + "styles": [], + "tpl": null, + "etpl": null + } + ], [ "i-size", { @@ -2227,14 +2449,18 @@ "name": "p-components", "parent": "i-dynamic-page", "dependencies": [ - "b-tree" + "b-tree", + "b-components-panel", + "b-components-tree" ], "libs": [] }, "name": "p-components", "parent": "i-dynamic-page", "dependencies": [ - "b-tree" + "b-tree", + "b-components-panel", + "b-components-tree" ], "libs": [], "resolvedLibs": { @@ -2374,7 +2600,8 @@ "components/traits/i-control-list/i-control-list", "core/browser", "core/cookies", - "core/html" + "core/html", + "models/modules/session" ] }, "name": "p-v4-components-demo", @@ -2415,7 +2642,8 @@ "components/traits/i-control-list/i-control-list", "core/browser", "core/cookies", - "core/html" + "core/html", + "models/modules/session" ], "resolvedLibs": { "%data": "%data:Set", @@ -2429,7 +2657,8 @@ "core/cookies", "core/html", "core/router/engines/browser-history", - "core/router/engines/in-memory" + "core/router/engines/in-memory", + "models/modules/session" ] }, "resolvedOwnLibs": { @@ -2444,7 +2673,8 @@ "core/cookies", "core/html", "core/router/engines/browser-history", - "core/router/engines/in-memory" + "core/router/engines/in-memory", + "models/modules/session" ] }, "type": "page", diff --git a/packages/devtools-core/src/features/components/b-components-panel/interface.ts b/packages/devtools-core/src/features/components/b-components-panel/interface.ts index b85939f..6697d7b 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/interface.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/interface.ts @@ -33,6 +33,6 @@ export type ComponentData = { hierarchy: string[]; } & Pick< - ComponentMeta, 'componentName' | 'props' | 'fields' | 'computedFields' | 'systemFields' + ComponentMeta, 'componentName' | 'props' | 'fields' | 'computedFields' | 'systemFields' | 'mods' >; diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts index ac321de..4ac619d 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts @@ -12,6 +12,32 @@ import { normalizeComponentName } from 'core/helpers'; import type { Item, ComponentData } from 'features/components/b-components-panel/interface'; +/** + * An array of {@link ComponentData} items with specific value getter for each item + */ +const itemsWithGetters = [ + { + name: 'props', + getValue: (data, key) => data.values[key] + }, + { + name: 'fields', + getValue: (data, key) => data.values[key] + }, + { + name: 'computedFields', + getValue: (data, key) => data.values[key] + }, + { + name: 'mods', + getValue: (data, key) => Object.isDictionary(data.values.mods) ? data.values.mods[key] : undefined, + }, + { + name: 'systemFields', + getValue: (data, key) => data.values[key] + }, +]; + /** * Creates items from component data * @param data @@ -23,13 +49,12 @@ export function createItems(data: ComponentData): Item[] { [block, ...rest] = data.componentName.split('-'), selfRegex = new RegExp(`^(i|${block})-${rest.join('-')}-?`); - ['props', 'fields', 'computedFields', 'systemFields'].forEach((name) => { + itemsWithGetters.forEach(({name, getValue}) => { const dict = data[name]; const map = new Map(); const children: Item[] = []; Object.keys(dict).forEach((key) => { - if (key.startsWith('$')) { return; } @@ -40,7 +65,7 @@ export function createItems(data: ComponentData): Item[] { // Match intermediate classes isSelf = src == null || src.match(selfRegex) != null; - const [value, valueChildren] = prepareValue(data.values[key], key); + const [value, valueChildren] = prepareValue(getValue(data, key), key); const item: Item = { label: key, @@ -63,15 +88,15 @@ export function createItems(data: ComponentData): Item[] { }); data.hierarchy.forEach((parent) => { - const items = map.get(parent); + const childItems = map.get(parent); map.delete(parent); - if (items != null) { + if (childItems != null) { children.push({ label: parent.camelize(false), folded: true, - children: items + children: childItems }); } }); diff --git a/packages/devtools-extension/src/pages/p-components/p-components.ts b/packages/devtools-extension/src/pages/p-components/p-components.ts index ec50f7a..4c4b47c 100644 --- a/packages/devtools-extension/src/pages/p-components/p-components.ts +++ b/packages/devtools-extension/src/pages/p-components/p-components.ts @@ -154,7 +154,7 @@ function evalComponentMeta(value: string, name?: string): Nullable { throw new Error('DOM node doesn\'t have component property'); } - const {componentName, props, fields, computedFields, systemFields} = component.unsafe.meta; + const {componentName, props, fields, computedFields, systemFields, mods} = component.unsafe.meta; const values = {}; @@ -174,7 +174,17 @@ function evalComponentMeta(value: string, name?: string): Nullable { parent = parent.parentMeta; } - const result = {componentId: value, componentName, props, fields, computedFields, systemFields, hierarchy, values}; + const result = { + componentId: value, + componentName, + props, + fields, + computedFields, + systemFields, + mods, + hierarchy, + values + }; return globalThis.__V4FIRE_DEVTOOLS_BACKEND__.serialize( result, From 4c001ceaa273ea3414b4ddf329455c73aae6ef10 Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Thu, 14 Mar 2024 10:06:18 +0300 Subject: [PATCH 02/12] feat: select for mods in panel --- packages/devtools-core/components-lock.json | 66 +++++++++++++++--- .../src/assets/svg/caret-down.svg | 3 + .../devtools-core/src/assets/svg/warning.svg | 3 + .../form/b-custom-select/b-custom-select.ss | 8 +++ .../form/b-custom-select/b-custom-select.styl | 17 +++++ .../form/b-custom-select/b-custom-select.ts | 35 ++++++++++ .../components/form/b-custom-select/index.js | 12 ++++ .../b-components-panel.styl | 1 + .../b-components-panel/b-components-panel.ts | 12 +++- .../b-components-panel/interface.ts | 9 +++ .../b-components-panel-item.ss | 23 ++++++- .../b-components-panel-item.styl | 12 ++++ .../b-components-panel-item.ts | 6 ++ .../modules/b-components-panel-item/index.js | 4 +- .../b-components-panel/modules/helpers.ts | 69 +++++++++++++++---- .../devtools-extension/components-lock.json | 66 +++++++++++++++--- .../b-components-panel/b-components-panel.ts | 23 ++++++- 17 files changed, 334 insertions(+), 35 deletions(-) create mode 100644 packages/devtools-core/src/assets/svg/caret-down.svg create mode 100644 packages/devtools-core/src/assets/svg/warning.svg create mode 100644 packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ss create mode 100644 packages/devtools-core/src/components/form/b-custom-select/b-custom-select.styl create mode 100644 packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts create mode 100644 packages/devtools-core/src/components/form/b-custom-select/index.js create mode 100644 packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl diff --git a/packages/devtools-core/components-lock.json b/packages/devtools-core/components-lock.json index 89719d6..fa184fb 100644 --- a/packages/devtools-core/components-lock.json +++ b/packages/devtools-core/components-lock.json @@ -1,5 +1,5 @@ { - "hash": "b68f8922f12b1ef2d5f3b9d117610914aaffcfa437c5d518b0f27cf1d80f1750", + "hash": "8a119842339a3eed678939571dba68d0986c2d39924b57a1c86a198d1630647c", "data": { "%data": "%data:Map", "%data:Map": [ @@ -198,25 +198,41 @@ "declaration": { "name": "b-components-panel-item", "parent": "i-block", - "dependencies": [], - "libs": [] + "dependencies": [ + "b-custom-select", + "b-button" + ], + "libs": [ + "components/directives/icon" + ] }, "name": "b-components-panel-item", "parent": "i-block", - "dependencies": [], - "libs": [], + "dependencies": [ + "b-custom-select", + "b-button" + ], + "libs": [ + "components/directives/icon" + ], "resolvedLibs": { "%data": "%data:Set", - "%data:Set": [] + "%data:Set": [ + "components/directives/icon" + ] }, "resolvedOwnLibs": { "%data": "%data:Set", - "%data:Set": [] + "%data:Set": [ + "components/directives/icon" + ] }, "type": "block", "mixin": false, "logic": "src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts", - "styles": [], + "styles": [ + "src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl" + ], "tpl": "src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss", "etpl": null } @@ -301,6 +317,40 @@ "etpl": null } ], + [ + "b-custom-select", + { + "index": "src/components/form/b-custom-select/index.js", + "declaration": { + "name": "b-custom-select", + "parent": "b-select", + "dependencies": [], + "libs": [] + }, + "name": "b-custom-select", + "parent": "b-select", + "dependencies": [], + "libs": [], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [ + "components/directives/icon" + ] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "type": "block", + "mixin": false, + "logic": "src/components/form/b-custom-select/b-custom-select.ts", + "styles": [ + "src/components/form/b-custom-select/b-custom-select.styl" + ], + "tpl": "src/components/form/b-custom-select/b-custom-select.ss", + "etpl": null + } + ], [ "b-dummy", { diff --git a/packages/devtools-core/src/assets/svg/caret-down.svg b/packages/devtools-core/src/assets/svg/caret-down.svg new file mode 100644 index 0000000..edd826d --- /dev/null +++ b/packages/devtools-core/src/assets/svg/caret-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/devtools-core/src/assets/svg/warning.svg b/packages/devtools-core/src/assets/svg/warning.svg new file mode 100644 index 0000000..d11bd1b --- /dev/null +++ b/packages/devtools-core/src/assets/svg/warning.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ss b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ss new file mode 100644 index 0000000..2b3767d --- /dev/null +++ b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ss @@ -0,0 +1,8 @@ +- namespace [%fileName%] + +- include '@super/components/form/b-select'|b as placeholder + +- template index() extends ['b-select'].index + - block input + < .&__value + {{ value }} diff --git a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.styl b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.styl new file mode 100644 index 0000000..39143da --- /dev/null +++ b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.styl @@ -0,0 +1,17 @@ +@import "@super/components/form/b-select/b-select.styl" + +b-custom-select extends b-select + &__dropdown + absolute left 0 top 100% + border 1px solid black + background-color white + + &__value + margin-right 4px + + &__wrapper + cursor pointer + + &__item_selected_true + &__item_marked_true + background-color rgba(100, 100, 100, 0.1) diff --git a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts new file mode 100644 index 0000000..3e9adaa --- /dev/null +++ b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts @@ -0,0 +1,35 @@ +/*! + * V4Fire DevTools + * https://github.com/V4Fire/DevTools + * + * Released under the MIT license + * https://github.com/V4Fire/DevTools/blob/main/LICENSE + */ + +import bSelect, { component, field } from '@v4fire/client/components/form/b-select/b-select'; +import iActiveItems from 'components/traits/i-active-items/i-active-items'; +import Block, { elements } from 'components/friends/block'; + +export * from '@v4fire/client/components/form/b-select/b-select'; + +// TODO: remove after fixing in `@v4fire/client` https://github.com/V4Fire/Client/pull/1177 +Block.addToPrototype({elements}); + +@component({functional: false}) +export default class bCustomSelect extends bSelect { + @field({ + unique: true, + init: (o) => { + o.watch('valueProp', (val) => o.setActive(val, true)); + o.watch('modelValue', (val) => o.setActive(val, true)); + return iActiveItems.linkActiveStore(o, (val) => o.resolveValue(o.valueProp ?? o.modelValue ?? val)); + } + }) + override activeStore!: iActiveItems['activeStore']; + + override async focus(): Promise { + await this.open(); + + return super.focus(); + } +} diff --git a/packages/devtools-core/src/components/form/b-custom-select/index.js b/packages/devtools-core/src/components/form/b-custom-select/index.js new file mode 100644 index 0000000..b6de9d3 --- /dev/null +++ b/packages/devtools-core/src/components/form/b-custom-select/index.js @@ -0,0 +1,12 @@ +/*! + * V4Fire DevTools + * https://github.com/V4Fire/DevTools + * + * Released under the MIT license + * https://github.com/V4Fire/DevTools/blob/main/LICENSE + */ + +'use strict'; + +package('b-custom-select') + .extends('b-select'); diff --git a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.styl b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.styl index 5ccd219..e050fe5 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.styl +++ b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.styl @@ -14,6 +14,7 @@ b-components-panel extends i-block line-height 1 &__body + flex-grow 1 overflow auto padding 4px 0 word-break break-word diff --git a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts index b7194b7..542b053 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts @@ -42,7 +42,7 @@ export default class bComponentsPanel extends iBlock { */ @field((o) => o.sync.link( 'componentData', - (val) => createItems(val) + (val) => createItems(o, val) )) protected itemsStore: Item[] = []; @@ -111,6 +111,16 @@ export default class bComponentsPanel extends iBlock { }; } + /** + * Change selected component mod + * + * @param _key + * @param _value + */ + onChangeMod(_key: string, _value: unknown): void { + // TODO: use inspected app + } + /** * Update show empty */ diff --git a/packages/devtools-core/src/features/components/b-components-panel/interface.ts b/packages/devtools-core/src/features/components/b-components-panel/interface.ts index 6697d7b..51dc5bf 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/interface.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/interface.ts @@ -7,6 +7,8 @@ */ import type { Item as Super, ComponentMeta } from 'components/base/b-tree/b-tree'; +import type { Item as SelectItem } from 'components/form/b-select/b-select'; +import type bSelect from 'components/form/b-select/b-select'; export interface Item extends Super { data?: unknown; @@ -14,6 +16,13 @@ export interface Item extends Super { path?: string; children?: Item[]; + + select?: { + items: SelectItem[]; + onActionChange(ctx: bSelect, value: unknown): void; + }; + + warning?: string; } export type ComponentData = { diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss index 5d45c53..cf94ab3 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss @@ -4,9 +4,28 @@ - template index() extends ['i-block'].index - block body - {{ label }}{{ data != null ? ': ' : null }} + < .&__label + {{ label }} - < template v-if = data != null + < span v-if = data != null || Object.size(field.get('select.items')) > 0 + \: + + < span.&__warning-icon & + v-if = warning != null | + :-hint = warning | + :class = provide.hintClasses('bottom-right') + . + < .g-icon v-icon:warning + + < b-custom-select.&__value & + v-if = Object.size(field.get('select.items')) > 0 | + :v-attrs = select | + :icon = 'caret-down' | + :cancellable = false | + :value = data + . + + < span.&__value v-else-if = data != null < template v-if = isFunction(data) < b-button @click = () => showFunction(data) Function diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl new file mode 100644 index 0000000..1795384 --- /dev/null +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl @@ -0,0 +1,12 @@ +@import "components/super/i-block/i-block.styl" + +b-components-panel-item extends i-block + flex-row def + word-break normal + + &__label + flex-row def + + &__warning-icon + &__value + margin-left 4px diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts index 4062ad8..362d052 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts @@ -16,6 +16,12 @@ export default class bComponentsPanelItem extends iBlock { @prop() data: unknown; + @prop() + select?: Dictionary; + + @prop({type: String}) + warning?: string; + isFunction(data: unknown): boolean { return String(data) === 'Function' && Object.hasOwnProperty.call(data, 'declaration'); } diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js index 347041d..0202461 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js @@ -9,4 +9,6 @@ 'use strict'; package('b-components-panel-item') - .extends('i-block'); + .extends('i-block') + .dependencies('b-custom-select', 'b-button') + .libs('components/directives/icon'); diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts index 4ac619d..66bb743 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts @@ -8,49 +8,87 @@ import { getType } from '@v4fire/devtools-backend'; -import { normalizeComponentName } from 'core/helpers'; +import { NBSP, normalizeComponentName } from 'core/helpers'; import type { Item, ComponentData } from 'features/components/b-components-panel/interface'; +import type bComponentsPanel from 'features/components/b-components-panel/b-components-panel'; + +interface PanelItem { + name: string; + getValue(ctx: bComponentsPanel, data: ComponentData, key: string): {value: unknown; select?: Item['select']; warning?: Item['warning']}; + getDict(data: ComponentData): ComponentData[keyof ComponentData]; +} /** - * An array of {@link ComponentData} items with specific value getter for each item + * The panel items that should display for the selected component */ -const itemsWithGetters = [ +const panelItems: PanelItem[] = [ { name: 'props', - getValue: (data, key) => data.values[key] + getValue: (_ctx, data, key) => ({value: data.values[key]}), + getDict: (data) => data.props }, { name: 'fields', - getValue: (data, key) => data.values[key] + getValue: (_ctx, data, key) => ({value: data.values[key]}), + getDict: (data) => data.fields }, { name: 'computedFields', - getValue: (data, key) => data.values[key] + getValue: (_ctx, data, key) => ({value: data.values[key]}), + getDict: (data) => data.computedFields }, { name: 'mods', - getValue: (data, key) => Object.isDictionary(data.values.mods) ? data.values.mods[key] : undefined, + getValue: (ctx, data, key) => { + let value = Object.isDictionary(data.values.mods) ? data.values.mods[key] : undefined; + + if (key in data.mods && Array.isArray(data.mods[key])) { + const items = data.mods[key]!.map((decl) => { + let declFormatted = String(decl); + + if (Array.isArray(decl)) { + declFormatted = String(decl[0]); + value ??= declFormatted; + } + + return {label: declFormatted, value: declFormatted}; + }); + + const select = { + items, + onActionChange: (_, value) => ctx.onChangeMod(key, value) + }; + + return {value, select}; + } + + return {value, warning: `Undeclared${NBSP}modifier`}; + }, + getDict: (data) => Object.mixin({}, {}, data.values.mods, data.mods) }, { name: 'systemFields', - getValue: (data, key) => data.values[key] - }, + getValue: (_ctx, data, key) => ({value: data.values[key]}), + getDict: (data) => data.systemFields + } ]; /** * Creates items from component data + * + * @param ctx * @param data */ -export function createItems(data: ComponentData): Item[] { +export function createItems(ctx: bComponentsPanel, data: ComponentData): Item[] { const items: Item[] = []; const [block, ...rest] = data.componentName.split('-'), selfRegex = new RegExp(`^(i|${block})-${rest.join('-')}-?`); - itemsWithGetters.forEach(({name, getValue}) => { - const dict = data[name]; + panelItems.forEach(({name, getValue, getDict}) => { + const dict = getDict(data); const map = new Map(); const children: Item[] = []; @@ -65,12 +103,15 @@ export function createItems(data: ComponentData): Item[] { // Match intermediate classes isSelf = src == null || src.match(selfRegex) != null; - const [value, valueChildren] = prepareValue(getValue(data, key), key); + const {value: valueByKey, select, warning} = getValue(ctx, data, key); + const [value, valueChildren] = prepareValue(valueByKey, key); const item: Item = { label: key, data: value, - children: valueChildren + children: valueChildren, + select, + warning }; if (isSelf) { diff --git a/packages/devtools-extension/components-lock.json b/packages/devtools-extension/components-lock.json index e5a2de1..d61e4a4 100644 --- a/packages/devtools-extension/components-lock.json +++ b/packages/devtools-extension/components-lock.json @@ -1,5 +1,5 @@ { - "hash": "58e59f1cca95fb4176b0fe97bf942dff46345e67d15ce46a44d096d980fd702b", + "hash": "4d3c9a6bfa7c232f50debfed75f527f04d39cca9bf47099996b47592aa73a6af", "data": { "%data": "%data:Map", "%data:Map": [ @@ -198,25 +198,41 @@ "declaration": { "name": "b-components-panel-item", "parent": "i-block", - "dependencies": [], - "libs": [] + "dependencies": [ + "b-custom-select", + "b-button" + ], + "libs": [ + "components/directives/icon" + ] }, "name": "b-components-panel-item", "parent": "i-block", - "dependencies": [], - "libs": [], + "dependencies": [ + "b-custom-select", + "b-button" + ], + "libs": [ + "components/directives/icon" + ], "resolvedLibs": { "%data": "%data:Set", - "%data:Set": [] + "%data:Set": [ + "components/directives/icon" + ] }, "resolvedOwnLibs": { "%data": "%data:Set", - "%data:Set": [] + "%data:Set": [ + "components/directives/icon" + ] }, "type": "block", "mixin": false, "logic": "node_modules/@v4fire/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts", - "styles": [], + "styles": [ + "node_modules/@v4fire/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl" + ], "tpl": "node_modules/@v4fire/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss", "etpl": null } @@ -301,6 +317,40 @@ "etpl": null } ], + [ + "b-custom-select", + { + "index": "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/index.js", + "declaration": { + "name": "b-custom-select", + "parent": "b-select", + "dependencies": [], + "libs": [] + }, + "name": "b-custom-select", + "parent": "b-select", + "dependencies": [], + "libs": [], + "resolvedLibs": { + "%data": "%data:Set", + "%data:Set": [ + "components/directives/icon" + ] + }, + "resolvedOwnLibs": { + "%data": "%data:Set", + "%data:Set": [] + }, + "type": "block", + "mixin": false, + "logic": "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/b-custom-select.ts", + "styles": [ + "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/b-custom-select.styl" + ], + "tpl": "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/b-custom-select.ss", + "etpl": null + } + ], [ "b-dummy", { diff --git a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts index f3b0421..b6a4e0a 100644 --- a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts +++ b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts @@ -7,12 +7,19 @@ */ import { devtoolsEval } from 'core/browser-api'; -import { component } from 'components/super/i-block/i-block'; +import iBlock, { component } from 'components/super/i-block/i-block'; import Super from '@super/features/components/b-components-panel/b-components-panel'; @component() export default class bComponentsPanel extends Super { + override onChangeMod(key: string, value: unknown): void { + const {componentId, componentName} = this.componentData; + + devtoolsEval(evalSetComponentMod, [key, value, componentId, componentName]) + .catch(stderr); + } + protected override onInspect(): void { const {componentId, componentName} = this.componentData; @@ -41,3 +48,17 @@ function evalInspect(componentId: string, componentName: string): void { alert('Component\'s node not found'); } } + +function evalSetComponentMod(key: string, value: unknown, componentId: string, componentName: string) { + const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(componentId, componentName); + + if (node == null) { + return; + } + + const {component} = <{component?: iBlock} & Element>node; + + if (component != null) { + void component.setMod(key, value); + } +} From 0f280b768b69547e6ff17f51a0b34774337cc5b6 Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Tue, 19 Mar 2024 20:07:14 +0300 Subject: [PATCH 03/12] chore: resolve todo --- .../src/components/form/b-custom-select/b-custom-select.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts index 3e9adaa..784c373 100644 --- a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts +++ b/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts @@ -8,13 +8,9 @@ import bSelect, { component, field } from '@v4fire/client/components/form/b-select/b-select'; import iActiveItems from 'components/traits/i-active-items/i-active-items'; -import Block, { elements } from 'components/friends/block'; export * from '@v4fire/client/components/form/b-select/b-select'; -// TODO: remove after fixing in `@v4fire/client` https://github.com/V4Fire/Client/pull/1177 -Block.addToPrototype({elements}); - @component({functional: false}) export default class bCustomSelect extends bSelect { @field({ From a3dc74169409047791a9f35cc1a05d15ae702d34 Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Thu, 21 Mar 2024 13:10:01 +0300 Subject: [PATCH 04/12] refactor: review fixes --- packages/devtools-core/components-lock.json | 50 +++++++++---------- .../b-dropdown.ss} | 2 +- .../b-dropdown.styl} | 2 +- .../b-dropdown.ts} | 4 +- .../{b-custom-select => b-dropdown}/index.js | 2 +- .../b-components-panel/b-components-panel.ss | 3 +- .../b-components-panel/b-components-panel.ts | 29 ++++++++++- .../b-components-panel/interface.ts | 12 ++--- .../b-components-panel-item.ss | 2 +- .../b-components-panel-item.styl | 4 +- .../b-components-panel-item.ts | 7 ++- .../modules/b-components-panel-item/index.js | 2 +- .../b-components-panel-item/interface.ts | 13 +++++ .../b-components-panel/modules/helpers.ts | 30 ++++------- .../devtools-extension/components-lock.json | 50 +++++++++---------- .../b-components-panel/b-components-panel.ts | 19 ++++--- .../b-components-panel/interface.ts | 11 ++++ 17 files changed, 146 insertions(+), 96 deletions(-) rename packages/devtools-core/src/components/form/{b-custom-select/b-custom-select.ss => b-dropdown/b-dropdown.ss} (65%) rename packages/devtools-core/src/components/form/{b-custom-select/b-custom-select.styl => b-dropdown/b-dropdown.styl} (89%) rename packages/devtools-core/src/components/form/{b-custom-select/b-custom-select.ts => b-dropdown/b-dropdown.ts} (91%) rename packages/devtools-core/src/components/form/{b-custom-select => b-dropdown}/index.js (87%) create mode 100644 packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/interface.ts create mode 100644 packages/devtools-extension/src/features/components/b-components-panel/interface.ts diff --git a/packages/devtools-core/components-lock.json b/packages/devtools-core/components-lock.json index 765d161..45ff562 100644 --- a/packages/devtools-core/components-lock.json +++ b/packages/devtools-core/components-lock.json @@ -1,5 +1,5 @@ { - "hash": "3705834372e15d17aadff21374e59d7ffa9f50b7776f1a0766cf96bbc922464c", + "hash": "b1f092ba867cc6f75520d31a06c0b387336890ccc7bbe045022f86c3856f3fa9", "data": { "%data": "%data:Map", "%data:Map": [ @@ -199,7 +199,7 @@ "name": "b-components-panel-item", "parent": "i-block", "dependencies": [ - "b-custom-select", + "b-dropdown", "b-button" ], "libs": [ @@ -209,7 +209,7 @@ "name": "b-components-panel-item", "parent": "i-block", "dependencies": [ - "b-custom-select", + "b-dropdown", "b-button" ], "libs": [ @@ -318,24 +318,22 @@ } ], [ - "b-custom-select", + "b-directives-ref-dummy", { - "index": "src/components/form/b-custom-select/index.js", + "index": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/index.js", "declaration": { - "name": "b-custom-select", - "parent": "b-select", + "name": "b-directives-ref-dummy", + "parent": "b-dummy", "dependencies": [], "libs": [] }, - "name": "b-custom-select", - "parent": "b-select", + "name": "b-directives-ref-dummy", + "parent": "b-dummy", "dependencies": [], "libs": [], "resolvedLibs": { "%data": "%data:Set", - "%data:Set": [ - "components/directives/icon" - ] + "%data:Set": [] }, "resolvedOwnLibs": { "%data": "%data:Set", @@ -343,31 +341,33 @@ }, "type": "block", "mixin": false, - "logic": "src/components/form/b-custom-select/b-custom-select.ts", + "logic": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ts", "styles": [ - "src/components/form/b-custom-select/b-custom-select.styl" + "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.styl" ], - "tpl": "src/components/form/b-custom-select/b-custom-select.ss", + "tpl": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ss", "etpl": null } ], [ - "b-directives-ref-dummy", + "b-dropdown", { - "index": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/index.js", + "index": "src/components/form/b-dropdown/index.js", "declaration": { - "name": "b-directives-ref-dummy", - "parent": "b-dummy", + "name": "b-dropdown", + "parent": "b-select", "dependencies": [], "libs": [] }, - "name": "b-directives-ref-dummy", - "parent": "b-dummy", + "name": "b-dropdown", + "parent": "b-select", "dependencies": [], "libs": [], "resolvedLibs": { "%data": "%data:Set", - "%data:Set": [] + "%data:Set": [ + "components/directives/icon" + ] }, "resolvedOwnLibs": { "%data": "%data:Set", @@ -375,11 +375,11 @@ }, "type": "block", "mixin": false, - "logic": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ts", + "logic": "src/components/form/b-dropdown/b-dropdown.ts", "styles": [ - "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.styl" + "src/components/form/b-dropdown/b-dropdown.styl" ], - "tpl": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ss", + "tpl": "src/components/form/b-dropdown/b-dropdown.ss", "etpl": null } ], diff --git a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ss b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss similarity index 65% rename from packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ss rename to packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss index 2b3767d..d322b95 100644 --- a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ss +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss @@ -1,6 +1,6 @@ - namespace [%fileName%] -- include '@super/components/form/b-select'|b as placeholder +- include 'components/form/b-select'|b as placeholder - template index() extends ['b-select'].index - block input diff --git a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.styl b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl similarity index 89% rename from packages/devtools-core/src/components/form/b-custom-select/b-custom-select.styl rename to packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl index 39143da..5a3653c 100644 --- a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.styl +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl @@ -1,6 +1,6 @@ @import "@super/components/form/b-select/b-select.styl" -b-custom-select extends b-select +b-dropdown extends b-select &__dropdown absolute left 0 top 100% border 1px solid black diff --git a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts similarity index 91% rename from packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts rename to packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts index 784c373..e7a1355 100644 --- a/packages/devtools-core/src/components/form/b-custom-select/b-custom-select.ts +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts @@ -12,8 +12,8 @@ import iActiveItems from 'components/traits/i-active-items/i-active-items'; export * from '@v4fire/client/components/form/b-select/b-select'; @component({functional: false}) -export default class bCustomSelect extends bSelect { - @field({ +export default class bDropdown extends bSelect { + @field({ unique: true, init: (o) => { o.watch('valueProp', (val) => o.setActive(val, true)); diff --git a/packages/devtools-core/src/components/form/b-custom-select/index.js b/packages/devtools-core/src/components/form/b-dropdown/index.js similarity index 87% rename from packages/devtools-core/src/components/form/b-custom-select/index.js rename to packages/devtools-core/src/components/form/b-dropdown/index.js index b6de9d3..fb74b3e 100644 --- a/packages/devtools-core/src/components/form/b-custom-select/index.js +++ b/packages/devtools-core/src/components/form/b-dropdown/index.js @@ -8,5 +8,5 @@ 'use strict'; -package('b-custom-select') +package('b-dropdown') .extends('b-select'); diff --git a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ss b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ss index 988f431..b0d7778 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ss +++ b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ss @@ -29,5 +29,6 @@ :items = items | :item = 'b-components-panel-item' | :theme = 'pretty' | - :cancelable = true + :cancelable = true | + :itemProps = getPanelItemProps . diff --git a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts index 3f9ecb7..d755b4d 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts @@ -12,6 +12,7 @@ import type bTree from 'components/base/b-tree/b-tree'; import type { Item, ComponentData } from 'features/components/b-components-panel/interface'; import { createItems } from 'features/components/b-components-panel/modules/helpers'; +import type bDropdown from 'components/form/b-dropdown/b-dropdown'; export * from 'features/components/b-components-panel/interface'; @@ -38,7 +39,7 @@ export default class bComponentsPanel extends iBlock { */ @field((o) => o.sync.link( 'componentData', - (val) => createItems(o, val) + (val) => createItems(val) )) protected itemsStore: Item[] = []; @@ -65,6 +66,32 @@ export default class bComponentsPanel extends iBlock { } } + /** + * Returns formatted props for panel item + * @param item + */ + protected getPanelItemProps(item: Item): Dictionary { + if (item.availableOptions != null) { + return { + ...item, + + select: { + items: item.availableOptions, + + '@actionChange': (_ctx: bDropdown, value: unknown): void => { + if (item.label == null) { + return; + } + + this.onChangeMod(item.label, value); + } + } + }; + } + + return item; + } + /** * Change selected component mod * diff --git a/packages/devtools-core/src/features/components/b-components-panel/interface.ts b/packages/devtools-core/src/features/components/b-components-panel/interface.ts index 51dc5bf..f067285 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/interface.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/interface.ts @@ -7,8 +7,11 @@ */ import type { Item as Super, ComponentMeta } from 'components/base/b-tree/b-tree'; -import type { Item as SelectItem } from 'components/form/b-select/b-select'; -import type bSelect from 'components/form/b-select/b-select'; + +export interface ItemOption { + label: string; + value: unknown; +} export interface Item extends Super { data?: unknown; @@ -17,10 +20,7 @@ export interface Item extends Super { children?: Item[]; - select?: { - items: SelectItem[]; - onActionChange(ctx: bSelect, value: unknown): void; - }; + availableOptions?: ItemOption[]; warning?: string; } diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss index cf94ab3..651cced 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss @@ -17,7 +17,7 @@ . < .g-icon v-icon:warning - < b-custom-select.&__value & + < b-dropdown.&__value & v-if = Object.size(field.get('select.items')) > 0 | :v-attrs = select | :icon = 'caret-down' | diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl index 1795384..b152c6f 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.styl @@ -1,11 +1,11 @@ @import "components/super/i-block/i-block.styl" b-components-panel-item extends i-block - flex-row def + display flex word-break normal &__label - flex-row def + display flex &__warning-icon &__value diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts index 362d052..97293ee 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ts @@ -7,6 +7,9 @@ */ import iBlock, { component, prop } from 'components/super/i-block/i-block'; +import type { PanelItemSelect } from 'features/components/b-components-panel/modules/b-components-panel-item/interface'; + +export * from 'features/components/b-components-panel/modules/b-components-panel-item/interface'; @component() export default class bComponentsPanelItem extends iBlock { @@ -16,8 +19,8 @@ export default class bComponentsPanelItem extends iBlock { @prop() data: unknown; - @prop() - select?: Dictionary; + @prop({type: Array}) + select?: PanelItemSelect; @prop({type: String}) warning?: string; diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js index 0202461..0abb628 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/index.js @@ -10,5 +10,5 @@ package('b-components-panel-item') .extends('i-block') - .dependencies('b-custom-select', 'b-button') + .dependencies('b-dropdown', 'b-button') .libs('components/directives/icon'); diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/interface.ts b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/interface.ts new file mode 100644 index 0000000..c6da694 --- /dev/null +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/interface.ts @@ -0,0 +1,13 @@ +/*! + * V4Fire DevTools + * https://github.com/V4Fire/DevTools + * + * Released under the MIT license + * https://github.com/V4Fire/DevTools/blob/main/LICENSE + */ + +import type bDropdown from 'components/form/b-dropdown/b-dropdown'; + +export interface PanelItemSelect extends Dictionary { + items: bDropdown['items']; +} diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts index 66bb743..a70f667 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts @@ -11,11 +11,10 @@ import { getType } from '@v4fire/devtools-backend'; import { NBSP, normalizeComponentName } from 'core/helpers'; import type { Item, ComponentData } from 'features/components/b-components-panel/interface'; -import type bComponentsPanel from 'features/components/b-components-panel/b-components-panel'; interface PanelItem { name: string; - getValue(ctx: bComponentsPanel, data: ComponentData, key: string): {value: unknown; select?: Item['select']; warning?: Item['warning']}; + getData(data: ComponentData, key: string): {value: unknown; items?: Item['availableOptions']; warning?: Item['warning']}; getDict(data: ComponentData): ComponentData[keyof ComponentData]; } @@ -25,22 +24,22 @@ interface PanelItem { const panelItems: PanelItem[] = [ { name: 'props', - getValue: (_ctx, data, key) => ({value: data.values[key]}), + getData: (data, key) => ({value: data.values[key]}), getDict: (data) => data.props }, { name: 'fields', - getValue: (_ctx, data, key) => ({value: data.values[key]}), + getData: (data, key) => ({value: data.values[key]}), getDict: (data) => data.fields }, { name: 'computedFields', - getValue: (_ctx, data, key) => ({value: data.values[key]}), + getData: (data, key) => ({value: data.values[key]}), getDict: (data) => data.computedFields }, { name: 'mods', - getValue: (ctx, data, key) => { + getData: (data, key) => { let value = Object.isDictionary(data.values.mods) ? data.values.mods[key] : undefined; if (key in data.mods && Array.isArray(data.mods[key])) { @@ -55,12 +54,7 @@ const panelItems: PanelItem[] = [ return {label: declFormatted, value: declFormatted}; }); - const select = { - items, - onActionChange: (_, value) => ctx.onChangeMod(key, value) - }; - - return {value, select}; + return {value, items}; } return {value, warning: `Undeclared${NBSP}modifier`}; @@ -69,25 +63,23 @@ const panelItems: PanelItem[] = [ }, { name: 'systemFields', - getValue: (_ctx, data, key) => ({value: data.values[key]}), + getData: (data, key) => ({value: data.values[key]}), getDict: (data) => data.systemFields } ]; /** * Creates items from component data - * - * @param ctx * @param data */ -export function createItems(ctx: bComponentsPanel, data: ComponentData): Item[] { +export function createItems(data: ComponentData): Item[] { const items: Item[] = []; const [block, ...rest] = data.componentName.split('-'), selfRegex = new RegExp(`^(i|${block})-${rest.join('-')}-?`); - panelItems.forEach(({name, getValue, getDict}) => { + panelItems.forEach(({name, getData, getDict}) => { const dict = getDict(data); const map = new Map(); const children: Item[] = []; @@ -103,14 +95,14 @@ export function createItems(ctx: bComponentsPanel, data: ComponentData): Item[] // Match intermediate classes isSelf = src == null || src.match(selfRegex) != null; - const {value: valueByKey, select, warning} = getValue(ctx, data, key); + const {value: valueByKey, items, warning} = getData(data, key); const [value, valueChildren] = prepareValue(valueByKey, key); const item: Item = { label: key, data: value, children: valueChildren, - select, + availableOptions: items, warning }; diff --git a/packages/devtools-extension/components-lock.json b/packages/devtools-extension/components-lock.json index 3e6114b..ff21c92 100644 --- a/packages/devtools-extension/components-lock.json +++ b/packages/devtools-extension/components-lock.json @@ -1,5 +1,5 @@ { - "hash": "52fa093205843bea1e32c9b0dc41b68929806909fda8f734c7838017179ee076", + "hash": "63d5c3bbc40479cff0829239c37b43c0a2a5a98e14bf6983e5d3a703cf1515e1", "data": { "%data": "%data:Map", "%data:Map": [ @@ -199,7 +199,7 @@ "name": "b-components-panel-item", "parent": "i-block", "dependencies": [ - "b-custom-select", + "b-dropdown", "b-button" ], "libs": [ @@ -209,7 +209,7 @@ "name": "b-components-panel-item", "parent": "i-block", "dependencies": [ - "b-custom-select", + "b-dropdown", "b-button" ], "libs": [ @@ -318,24 +318,22 @@ } ], [ - "b-custom-select", + "b-directives-ref-dummy", { - "index": "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/index.js", + "index": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/index.js", "declaration": { - "name": "b-custom-select", - "parent": "b-select", + "name": "b-directives-ref-dummy", + "parent": "b-dummy", "dependencies": [], "libs": [] }, - "name": "b-custom-select", - "parent": "b-select", + "name": "b-directives-ref-dummy", + "parent": "b-dummy", "dependencies": [], "libs": [], "resolvedLibs": { "%data": "%data:Set", - "%data:Set": [ - "components/directives/icon" - ] + "%data:Set": [] }, "resolvedOwnLibs": { "%data": "%data:Set", @@ -343,31 +341,33 @@ }, "type": "block", "mixin": false, - "logic": "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/b-custom-select.ts", + "logic": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ts", "styles": [ - "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/b-custom-select.styl" + "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.styl" ], - "tpl": "node_modules/@v4fire/devtools-core/src/components/form/b-custom-select/b-custom-select.ss", + "tpl": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ss", "etpl": null } ], [ - "b-directives-ref-dummy", + "b-dropdown", { - "index": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/index.js", + "index": "node_modules/@v4fire/devtools-core/src/components/form/b-dropdown/index.js", "declaration": { - "name": "b-directives-ref-dummy", - "parent": "b-dummy", + "name": "b-dropdown", + "parent": "b-select", "dependencies": [], "libs": [] }, - "name": "b-directives-ref-dummy", - "parent": "b-dummy", + "name": "b-dropdown", + "parent": "b-select", "dependencies": [], "libs": [], "resolvedLibs": { "%data": "%data:Set", - "%data:Set": [] + "%data:Set": [ + "components/directives/icon" + ] }, "resolvedOwnLibs": { "%data": "%data:Set", @@ -375,11 +375,11 @@ }, "type": "block", "mixin": false, - "logic": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ts", + "logic": "node_modules/@v4fire/devtools-core/src/components/form/b-dropdown/b-dropdown.ts", "styles": [ - "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.styl" + "node_modules/@v4fire/devtools-core/src/components/form/b-dropdown/b-dropdown.styl" ], - "tpl": "node_modules/@v4fire/client/src/core/component/directives/ref/test/b-directives-ref-dummy/b-directives-ref-dummy.ss", + "tpl": "node_modules/@v4fire/devtools-core/src/components/form/b-dropdown/b-dropdown.ss", "etpl": null } ], diff --git a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts index b6a4e0a..4b16e2a 100644 --- a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts +++ b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts @@ -7,28 +7,31 @@ */ import { devtoolsEval } from 'core/browser-api'; -import iBlock, { component } from 'components/super/i-block/i-block'; +import iBlock, { component, ComponentElement } from 'components/super/i-block/i-block'; import Super from '@super/features/components/b-components-panel/b-components-panel'; +import type { ComponentQuery } from 'features/components/b-components-panel/interface'; + +export * from 'features/components/b-components-panel/interface'; @component() export default class bComponentsPanel extends Super { override onChangeMod(key: string, value: unknown): void { const {componentId, componentName} = this.componentData; - devtoolsEval(evalSetComponentMod, [key, value, componentId, componentName]) + devtoolsEval(evalSetComponentMod, [key, value, {componentId, componentName}]) .catch(stderr); } protected override onInspect(): void { const {componentId, componentName} = this.componentData; - devtoolsEval(evalInspect, [componentId, componentName]) + devtoolsEval(evalInspect, [{componentId, componentName}]) .catch(stderr); } } -function evalInspect(componentId: string, componentName: string): void { +function evalInspect(query: ComponentQuery): void { // eslint-disable-next-line @typescript-eslint/method-signature-style const {inspect} = <{inspect?: (el: Element) => void} & Global>globalThis; @@ -38,7 +41,7 @@ function evalInspect(componentId: string, componentName: string): void { return; } - const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(componentId, componentName); + const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(query.componentId, query.componentName); if (node != null) { inspect(node); @@ -49,14 +52,14 @@ function evalInspect(componentId: string, componentName: string): void { } } -function evalSetComponentMod(key: string, value: unknown, componentId: string, componentName: string) { - const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(componentId, componentName); +function evalSetComponentMod(key: string, value: unknown, query: ComponentQuery) { + const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(query.componentId, query.componentName); if (node == null) { return; } - const {component} = <{component?: iBlock} & Element>node; + const {component} = >node; if (component != null) { void component.setMod(key, value); diff --git a/packages/devtools-extension/src/features/components/b-components-panel/interface.ts b/packages/devtools-extension/src/features/components/b-components-panel/interface.ts new file mode 100644 index 0000000..4fccec0 --- /dev/null +++ b/packages/devtools-extension/src/features/components/b-components-panel/interface.ts @@ -0,0 +1,11 @@ +/*! + * V4Fire DevTools + * https://github.com/V4Fire/DevTools + * + * Released under the MIT license + * https://github.com/V4Fire/DevTools/blob/main/LICENSE + */ + +import type { ComponentInterface } from 'core/component'; + +export type ComponentQuery = Pick; From 4138c9686039abbf3458a7326b85af98008560c9 Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Thu, 21 Mar 2024 13:33:32 +0300 Subject: [PATCH 05/12] feat: button wrapper for dropdown trigger --- .../src/components/form/b-dropdown/b-dropdown.ss | 6 +++++- .../src/components/form/b-dropdown/b-dropdown.styl | 5 ++++- .../src/components/form/b-dropdown/b-dropdown.ts | 6 ------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss index d322b95..6760daf 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss @@ -3,6 +3,10 @@ - include 'components/form/b-select'|b as placeholder - template index() extends ['b-select'].index - - block input + - block nativeInput() < .&__value {{ value }} + + - block body + < button.&__trigger @click = open + - super diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl index 5a3653c..1fe0619 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl @@ -9,8 +9,11 @@ b-dropdown extends b-select &__value margin-right 4px + &__trigger + border none + &__wrapper - cursor pointer + cursor inherit &__item_selected_true &__item_marked_true diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts index e7a1355..7f7c9bd 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts @@ -22,10 +22,4 @@ export default class bDropdown extends bSelect { } }) override activeStore!: iActiveItems['activeStore']; - - override async focus(): Promise { - await this.open(); - - return super.focus(); - } } From 98c8b856f78ff9d9863e60f347dc274af25e3845 Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Thu, 21 Mar 2024 18:22:58 +0300 Subject: [PATCH 06/12] fix: b-dropdown keyboard interaction --- .../devtools-core/src/components/form/b-dropdown/b-dropdown.ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss index 6760daf..474ae04 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss @@ -8,5 +8,5 @@ {{ value }} - block body - < button.&__trigger @click = open + < button.&__trigger @click = onFocus - super From d5bd7569de68a614e57aae6ae12270eaa2bc83b6 Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Tue, 2 Apr 2024 01:14:07 +0300 Subject: [PATCH 07/12] fix: b-dropdown keyboard interaction --- .../src/components/form/b-dropdown/b-dropdown.ss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss index 474ae04..7ada1dc 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss @@ -8,5 +8,8 @@ {{ value }} - block body - < button.&__trigger @click = onFocus + < button.&__trigger & + @focus = onFocus | + @blur = onBlur + . - super From 0dcefa521f2585914f95f5246db6597ac57c74be Mon Sep 17 00:00:00 2001 From: Magomed Chemurziev Date: Wed, 3 Apr 2024 00:05:08 +0300 Subject: [PATCH 08/12] fix: review fixes --- .../src/core/component/index.ts} | 4 +--- .../src/core/component/interface/index.ts | 23 +++++++++++++++++++ packages/devtools-backend/src/index.ts | 1 + .../components/form/b-dropdown/b-dropdown.ts | 4 ++-- .../b-components-panel/b-components-panel.ts | 8 +++---- .../b-components-panel/interface.ts | 2 +- .../b-components-panel/modules/helpers.ts | 12 +++++----- .../b-components-panel/b-components-panel.ts | 6 +++-- 8 files changed, 42 insertions(+), 18 deletions(-) rename packages/{devtools-extension/src/features/components/b-components-panel/interface.ts => devtools-backend/src/core/component/index.ts} (51%) create mode 100644 packages/devtools-backend/src/core/component/interface/index.ts diff --git a/packages/devtools-extension/src/features/components/b-components-panel/interface.ts b/packages/devtools-backend/src/core/component/index.ts similarity index 51% rename from packages/devtools-extension/src/features/components/b-components-panel/interface.ts rename to packages/devtools-backend/src/core/component/index.ts index 4fccec0..4352a07 100644 --- a/packages/devtools-extension/src/features/components/b-components-panel/interface.ts +++ b/packages/devtools-backend/src/core/component/index.ts @@ -6,6 +6,4 @@ * https://github.com/V4Fire/DevTools/blob/main/LICENSE */ -import type { ComponentInterface } from 'core/component'; - -export type ComponentQuery = Pick; +export * from './interface'; diff --git a/packages/devtools-backend/src/core/component/interface/index.ts b/packages/devtools-backend/src/core/component/interface/index.ts new file mode 100644 index 0000000..d064074 --- /dev/null +++ b/packages/devtools-backend/src/core/component/interface/index.ts @@ -0,0 +1,23 @@ +/*! + * V4Fire DevTools + * https://github.com/V4Fire/DevTools + * + * Released under the MIT license + * https://github.com/V4Fire/DevTools/blob/main/LICENSE + */ + +/** + * Parameters to search for a component + */ +export interface ComponentQuery { + /** + * The unique component identifier. + * The value is formed based on the passed prop or dynamically. + */ + readonly componentId: string; + + /** + * The component name in dash-style without special postfixes like `-functional` + */ + readonly componentName: string; +} diff --git a/packages/devtools-backend/src/index.ts b/packages/devtools-backend/src/index.ts index 18d0247..96513d2 100644 --- a/packages/devtools-backend/src/index.ts +++ b/packages/devtools-backend/src/index.ts @@ -9,3 +9,4 @@ export * from './serialize'; export * from './search'; export * from './ui'; +export * from './core/component'; diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts index 7f7c9bd..ce60bd9 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts @@ -6,10 +6,10 @@ * https://github.com/V4Fire/DevTools/blob/main/LICENSE */ -import bSelect, { component, field } from '@v4fire/client/components/form/b-select/b-select'; +import bSelect, { component, field } from 'components/form/b-select/b-select'; import iActiveItems from 'components/traits/i-active-items/i-active-items'; -export * from '@v4fire/client/components/form/b-select/b-select'; +export * from 'components/form/b-select/b-select'; @component({functional: false}) export default class bDropdown extends bSelect { diff --git a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts index d755b4d..98f4dae 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/b-components-panel.ts @@ -71,19 +71,19 @@ export default class bComponentsPanel extends iBlock { * @param item */ protected getPanelItemProps(item: Item): Dictionary { - if (item.availableOptions != null) { + if (item.allowedValues != null) { return { ...item, select: { - items: item.availableOptions, + items: item.allowedValues.map((value) => ({label: value, value})), '@actionChange': (_ctx: bDropdown, value: unknown): void => { if (item.label == null) { return; } - this.onChangeMod(item.label, value); + this.onItemChangeMod(item.label, value); } } }; @@ -98,7 +98,7 @@ export default class bComponentsPanel extends iBlock { * @param _key * @param _value */ - onChangeMod(_key: string, _value: unknown): void { + protected onItemChangeMod(_key: string, _value: unknown): void { // TODO: use inspected app } diff --git a/packages/devtools-core/src/features/components/b-components-panel/interface.ts b/packages/devtools-core/src/features/components/b-components-panel/interface.ts index f067285..2f2e1ef 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/interface.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/interface.ts @@ -20,7 +20,7 @@ export interface Item extends Super { children?: Item[]; - availableOptions?: ItemOption[]; + allowedValues?: string[]; warning?: string; } diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts index a70f667..8e52688 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/helpers.ts @@ -14,7 +14,7 @@ import type { Item, ComponentData } from 'features/components/b-components-panel interface PanelItem { name: string; - getData(data: ComponentData, key: string): {value: unknown; items?: Item['availableOptions']; warning?: Item['warning']}; + getData(data: ComponentData, key: string): {value: unknown; allowedValues?: Item['allowedValues']; warning?: Item['warning']}; getDict(data: ComponentData): ComponentData[keyof ComponentData]; } @@ -43,7 +43,7 @@ const panelItems: PanelItem[] = [ let value = Object.isDictionary(data.values.mods) ? data.values.mods[key] : undefined; if (key in data.mods && Array.isArray(data.mods[key])) { - const items = data.mods[key]!.map((decl) => { + const allowedValues = data.mods[key]!.map((decl) => { let declFormatted = String(decl); if (Array.isArray(decl)) { @@ -51,10 +51,10 @@ const panelItems: PanelItem[] = [ value ??= declFormatted; } - return {label: declFormatted, value: declFormatted}; + return declFormatted; }); - return {value, items}; + return {value, allowedValues}; } return {value, warning: `Undeclared${NBSP}modifier`}; @@ -95,14 +95,14 @@ export function createItems(data: ComponentData): Item[] { // Match intermediate classes isSelf = src == null || src.match(selfRegex) != null; - const {value: valueByKey, items, warning} = getData(data, key); + const {value: valueByKey, allowedValues, warning} = getData(data, key); const [value, valueChildren] = prepareValue(valueByKey, key); const item: Item = { label: key, data: value, children: valueChildren, - availableOptions: items, + allowedValues, warning }; diff --git a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts index 4b16e2a..07ac350 100644 --- a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts +++ b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts @@ -5,18 +5,20 @@ * Released under the MIT license * https://github.com/V4Fire/DevTools/blob/main/LICENSE */ + +import type { ComponentQuery } from '@v4fire/devtools-backend'; + import { devtoolsEval } from 'core/browser-api'; import iBlock, { component, ComponentElement } from 'components/super/i-block/i-block'; import Super from '@super/features/components/b-components-panel/b-components-panel'; -import type { ComponentQuery } from 'features/components/b-components-panel/interface'; export * from 'features/components/b-components-panel/interface'; @component() export default class bComponentsPanel extends Super { - override onChangeMod(key: string, value: unknown): void { + protected override onItemChangeMod(key: string, value: unknown): void { const {componentId, componentName} = this.componentData; devtoolsEval(evalSetComponentMod, [key, value, {componentId, componentName}]) From 73029f070fe7eaf858327c3541605b9e0c865552 Mon Sep 17 00:00:00 2001 From: Artem Shinkaruk Date: Fri, 26 Apr 2024 18:39:24 +0700 Subject: [PATCH 09/12] fix(b-dropdown): UI/UX - close dropdown on click - improve UI of the icon - default icon = caret-down --- .../src/components/form/b-dropdown/b-dropdown.ss | 1 + .../src/components/form/b-dropdown/b-dropdown.styl | 9 +++++++++ .../src/components/form/b-dropdown/b-dropdown.ts | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss index 7ada1dc..ba6aa8a 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ss @@ -9,6 +9,7 @@ - block body < button.&__trigger & + @click = toggle | @focus = onFocus | @blur = onBlur . diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl index 1fe0619..88e1d02 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.styl @@ -3,6 +3,7 @@ b-dropdown extends b-select &__dropdown absolute left 0 top 100% + overflow-x hidden border 1px solid black background-color white @@ -15,6 +16,14 @@ b-dropdown extends b-select &__wrapper cursor inherit + &__icon + height 1em + font-size 0.875rem + transition transform 0.15s + + &_opened_true ^[0]__icon + transform rotate(-180deg) + &__item_selected_true &__item_marked_true background-color rgba(100, 100, 100, 0.1) diff --git a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts index ce60bd9..b171654 100644 --- a/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts +++ b/packages/devtools-core/src/components/form/b-dropdown/b-dropdown.ts @@ -13,6 +13,8 @@ export * from 'components/form/b-select/b-select'; @component({functional: false}) export default class bDropdown extends bSelect { + override readonly icon: string = 'caret-down'; + @field({ unique: true, init: (o) => { @@ -22,4 +24,11 @@ export default class bDropdown extends bSelect { } }) override activeStore!: iActiveItems['activeStore']; + + /** + * Overriding the `onFocus` because dropdown shouldn't be opened on focus + */ + protected override onFocus(): void { + this.setMod('focused', 'true'); + } } From 83ed1bcaf22e99e20f518bbf7806fde85bcbea44 Mon Sep 17 00:00:00 2001 From: Artem Shinkaruk Date: Fri, 26 Apr 2024 18:39:48 +0700 Subject: [PATCH 10/12] chore(b-components-panel-item): remove icon prop from b-dropdown --- .../modules/b-components-panel-item/b-components-panel-item.ss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss index 651cced..30d607b 100644 --- a/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss +++ b/packages/devtools-core/src/features/components/b-components-panel/modules/b-components-panel-item/b-components-panel-item.ss @@ -20,7 +20,6 @@ < b-dropdown.&__value & v-if = Object.size(field.get('select.items')) > 0 | :v-attrs = select | - :icon = 'caret-down' | :cancellable = false | :value = data . From c027834f11b20f29ef121c4d78e4d65c2ae72508 Mon Sep 17 00:00:00 2001 From: Artem Shinkaruk Date: Fri, 26 Apr 2024 19:06:47 +0700 Subject: [PATCH 11/12] chore(devtools-backend): create interface directory --- packages/devtools-backend/src/index.ts | 2 +- .../component/interface/index.ts => interface/component.ts} | 2 +- .../devtools-backend/src/{core/component => interface}/index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename packages/devtools-backend/src/{core/component/interface/index.ts => interface/component.ts} (93%) rename packages/devtools-backend/src/{core/component => interface}/index.ts (84%) diff --git a/packages/devtools-backend/src/index.ts b/packages/devtools-backend/src/index.ts index 96513d2..768e5a5 100644 --- a/packages/devtools-backend/src/index.ts +++ b/packages/devtools-backend/src/index.ts @@ -9,4 +9,4 @@ export * from './serialize'; export * from './search'; export * from './ui'; -export * from './core/component'; +export * from './interface'; diff --git a/packages/devtools-backend/src/core/component/interface/index.ts b/packages/devtools-backend/src/interface/component.ts similarity index 93% rename from packages/devtools-backend/src/core/component/interface/index.ts rename to packages/devtools-backend/src/interface/component.ts index d064074..ae33a19 100644 --- a/packages/devtools-backend/src/core/component/interface/index.ts +++ b/packages/devtools-backend/src/interface/component.ts @@ -19,5 +19,5 @@ export interface ComponentQuery { /** * The component name in dash-style without special postfixes like `-functional` */ - readonly componentName: string; + readonly componentName?: string; } diff --git a/packages/devtools-backend/src/core/component/index.ts b/packages/devtools-backend/src/interface/index.ts similarity index 84% rename from packages/devtools-backend/src/core/component/index.ts rename to packages/devtools-backend/src/interface/index.ts index 4352a07..2b172cf 100644 --- a/packages/devtools-backend/src/core/component/index.ts +++ b/packages/devtools-backend/src/interface/index.ts @@ -6,4 +6,4 @@ * https://github.com/V4Fire/DevTools/blob/main/LICENSE */ -export * from './interface'; +export * from './component'; From 6edc2385c815dbf9ed01ceb766d2563ab3a006c7 Mon Sep 17 00:00:00 2001 From: Artem Shinkaruk Date: Fri, 26 Apr 2024 19:07:59 +0700 Subject: [PATCH 12/12] refactor(devtools-backend): use ComponentQuery to search/highlight components --- .../src/search/find-component-node.ts | 8 +++++--- .../src/ui/component-highlight.ts | 8 ++++---- .../devtools-backend/src/ui/component-locate.ts | 3 +-- .../b-components-panel/b-components-panel.ts | 4 ++-- .../b-components-tree/b-components-tree.ts | 15 ++++++++------- .../src/pages/p-components/p-components.ts | 2 +- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/packages/devtools-backend/src/search/find-component-node.ts b/packages/devtools-backend/src/search/find-component-node.ts index a9b2fc4..6cbb44f 100644 --- a/packages/devtools-backend/src/search/find-component-node.ts +++ b/packages/devtools-backend/src/search/find-component-node.ts @@ -6,13 +6,15 @@ * https://github.com/V4Fire/DevTools/blob/main/LICENSE */ +import type { ComponentQuery } from '../interface'; + /** * Find component DOM node * - * @param id - component id - * @param name - component name + * @param query - component query */ -export default function findComponentNode(id: string, name?: string): T | null { +export default function findComponentNode(query: ComponentQuery): T | null { + const {componentId: id, componentName: name} = query; let node = Array.prototype.find.call( document.querySelectorAll(`.i-block-helper.${id}`), (node) => node.component?.componentId === id diff --git a/packages/devtools-backend/src/ui/component-highlight.ts b/packages/devtools-backend/src/ui/component-highlight.ts index 039ac7e..6f3b935 100644 --- a/packages/devtools-backend/src/ui/component-highlight.ts +++ b/packages/devtools-backend/src/ui/component-highlight.ts @@ -6,6 +6,7 @@ * https://github.com/V4Fire/DevTools/blob/main/LICENSE */ +import type { ComponentQuery } from '../interface'; import findComponentNode from '../search/find-component-node'; interface HideOptions { @@ -26,11 +27,10 @@ class ComponentHighlight { /** * Show highlight for the component * - * @param componentId - * @param componentName + * @param query */ - show(componentId: string, componentName: string): void { - const node = findComponentNode(componentId, componentName); + show(query: ComponentQuery): void { + const node = findComponentNode(query); if (node == null) { return; diff --git a/packages/devtools-backend/src/ui/component-locate.ts b/packages/devtools-backend/src/ui/component-locate.ts index 21d4ed2..4e0f6e4 100644 --- a/packages/devtools-backend/src/ui/component-locate.ts +++ b/packages/devtools-backend/src/ui/component-locate.ts @@ -27,8 +27,7 @@ class ComponentLocate { component = e.target instanceof Element ? findComponent(e.target) : null; if (component != null) { - const {componentId, componentName} = component; - componentHighlight.show(componentId, componentName); + componentHighlight.show(component); } else { componentHighlight.hide(); diff --git a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts index 07ac350..d65c45a 100644 --- a/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts +++ b/packages/devtools-extension/src/features/components/b-components-panel/b-components-panel.ts @@ -43,7 +43,7 @@ function evalInspect(query: ComponentQuery): void { return; } - const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(query.componentId, query.componentName); + const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(query); if (node != null) { inspect(node); @@ -55,7 +55,7 @@ function evalInspect(query: ComponentQuery): void { } function evalSetComponentMod(key: string, value: unknown, query: ComponentQuery) { - const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(query.componentId, query.componentName); + const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(query); if (node == null) { return; diff --git a/packages/devtools-extension/src/features/components/b-components-tree/b-components-tree.ts b/packages/devtools-extension/src/features/components/b-components-tree/b-components-tree.ts index e2cf257..cbc00f6 100644 --- a/packages/devtools-extension/src/features/components/b-components-tree/b-components-tree.ts +++ b/packages/devtools-extension/src/features/components/b-components-tree/b-components-tree.ts @@ -6,6 +6,7 @@ * https://github.com/V4Fire/DevTools/blob/main/LICENSE */ +import type { ComponentQuery } from '@v4fire/devtools-backend'; import { devtoolsEval } from 'core/browser-api'; import { component, hook, system } from 'components/super/i-block/i-block'; @@ -31,7 +32,7 @@ export default class bComponentsTree extends Super { if (item != null) { devtoolsEval( evalHighlightActive, - [this.highlightedComponentId !== componentId, componentId, item.componentName] + [this.highlightedComponentId !== componentId, {componentId, componentName: item.componentName}] ) .catch(stderr); } @@ -45,7 +46,7 @@ export default class bComponentsTree extends Super { */ protected override onItemMouseEnter(item: Item): void { this.highlightedComponentId = item.value; - devtoolsEval(evalShowComponentHighlight, [item.value, item.componentName]).catch(stderr); + devtoolsEval(evalShowComponentHighlight, [{componentId: item.value, componentName: item.componentName}]).catch(stderr); } /** @@ -56,21 +57,21 @@ export default class bComponentsTree extends Super { } } -function evalHighlightActive(autoHide: boolean, ...args: [string, string]): void { +function evalHighlightActive(autoHide: boolean, query: ComponentQuery): void { const backend = globalThis.__V4FIRE_DEVTOOLS_BACKEND__; - const node = backend.findComponentNode(...args); + const node = backend.findComponentNode(query); // @ts-expect-error Non-standard API node?.scrollIntoViewIfNeeded(false); - backend.componentHighlight.show(...args); + backend.componentHighlight.show(query); if (autoHide) { backend.componentHighlight.hide({delay: 1500, animate: true}); } } -function evalShowComponentHighlight(...args: [string, string]): void { - globalThis.__V4FIRE_DEVTOOLS_BACKEND__.componentHighlight.show(...args); +function evalShowComponentHighlight(query: ComponentQuery): void { + globalThis.__V4FIRE_DEVTOOLS_BACKEND__.componentHighlight.show(query); } function evalHideComponentHighlight(): void { diff --git a/packages/devtools-extension/src/pages/p-components/p-components.ts b/packages/devtools-extension/src/pages/p-components/p-components.ts index 4c4b47c..1d8c56a 100644 --- a/packages/devtools-extension/src/pages/p-components/p-components.ts +++ b/packages/devtools-extension/src/pages/p-components/p-components.ts @@ -142,7 +142,7 @@ function evalComponentMeta(value: string, name?: string): Nullable { 'LANG_PACKS' ]); - const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode(value, name); + const node = globalThis.__V4FIRE_DEVTOOLS_BACKEND__.findComponentNode({componentId: value, componentName: name}); if (node == null) { return null;