@bpmn-io/properties-panel 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ All notable changes to [`@bpmn-io/properties-panel`](https://github.com/bpmn-io/
6
6
 
7
7
  ___Note:__ Yet to be released changes appear here._
8
8
 
9
+
10
+ ## 0.5.1
11
+
12
+ * `FEAT`: allow custom selector for `ListEntry#autoFocusEntry` (['4afae1'](https://github.com/bpmn-io/properties-panel/commit/4afae1ec0215417d961b176840f19e51ba8b9043))
13
+ * `FEAT`: add variable for monospace font (['354fc9'](https://github.com/bpmn-io/properties-panel/commit/354fc99c8e54c1eb3c8cb2bca20630172e7fad7b))
14
+
9
15
  ## 0.5.0
10
16
 
11
17
  * `FEAT`: add various design improvements ([#105](https://github.com/bpmn-io/properties-panel/pull/105))
@@ -91,6 +91,7 @@
91
91
  --line-height-condensed: 17px;
92
92
 
93
93
  --font-family: sans-serif;
94
+ --font-family-monospace: monospace;
94
95
 
95
96
  display: none;
96
97
  position: relative;
@@ -394,7 +395,7 @@ select.bio-properties-panel-input {
394
395
  }
395
396
 
396
397
  .bio-properties-panel-input-monospace {
397
- font-family: monospace;
398
+ font-family: var(--font-family-monospace);
398
399
  }
399
400
 
400
401
  .bio-properties-panel-input[type="checkbox"], .bio-properties-panel-input[type="radio"] {
@@ -17,7 +17,7 @@ import { ArrowIcon, CreateIcon, DeleteIcon } from '../icons';
17
17
  * @param {Function} [props.onRemove]
18
18
  * @param {Item[]} [props.items]
19
19
  * @param {boolean} [props.open]
20
- * @param {string} [props.autoFocusEntry]
20
+ * @param {string|boolean} [props.autoFocusEntry] either a custom selector string or true to focus the first input
21
21
  * @param {(a: Item, b: Item) => -1 | 0 | 1} [props.compareFn]
22
22
  * @returns
23
23
  */
@@ -123,8 +123,11 @@ function ItemsList(props) {
123
123
  const newItem = newItems[0];
124
124
  useEffect(() => {
125
125
  if (newItem && autoFocusEntry) {
126
- const entry = domQuery(`[data-entry-id="${id}"]`);
127
- const focusableInput = domQuery('.bio-properties-panel-input', entry);
126
+ // (0) select the parent entry (containing all list items)
127
+ const entry = domQuery(`[data-entry-id="${id}"]`); // (1) select the first input or a custom element to be focussed
128
+
129
+ const selector = typeof autoFocusEntry === 'boolean' ? '.bio-properties-panel-input' : autoFocusEntry;
130
+ const focusableInput = domQuery(selector, entry); // (2) set focus
128
131
 
129
132
  if (focusableInput) {
130
133
  if (isFunction(focusableInput.select)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/entries/List.js"],"names":["useEffect","useRef","useState","query","domQuery","isFunction","useKeyFactory","usePrevious","classnames","ArrowIcon","CreateIcon","DeleteIcon","List","props","id","element","items","renderItem","label","open","shouldOpen","onAdd","onRemove","autoFocusEntry","compareFn","setOpen","hasItems","length","toggleOpen","opening","elementChanged","shouldReset","sortedItems","useSortedItems","newItems","useNewItems","addItem","event","stopPropagation","ItemsList","getKey","newItem","entry","focusableInput","select","focus","map","item","index","key","currentItems","itemsRef","slice","current","sort","includes","unshift","push","filter","previousItems"],"mappings":"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","sourcesContent":["import {\n useEffect,\n useRef,\n useState\n} from 'preact/hooks';\n\nimport {\n query as domQuery\n} from 'min-dom';\n\nimport { isFunction } from 'min-dash';\n\nimport {\n useKeyFactory,\n usePrevious\n} from '../../hooks';\n\nimport classnames from 'classnames';\n\nimport {\n ArrowIcon,\n CreateIcon,\n DeleteIcon\n} from '../icons';\n\n/**\n * Entry for handling lists represented as nested entries.\n *\n * @template Item\n * @param {object} props\n * @param {string} props.id\n * @param {*} props.element\n * @param {Function} props.onAdd\n * @param {(item: Item, index: number, isNew: boolean) => JSX.Element} props.renderItem\n * @param {string} [props.label='<empty>']\n * @param {Function} [props.onRemove]\n * @param {Item[]} [props.items]\n * @param {boolean} [props.open]\n * @param {string} [props.autoFocusEntry]\n * @param {(a: Item, b: Item) => -1 | 0 | 1} [props.compareFn]\n * @returns\n */\nexport default function List(props) {\n const {\n id,\n element,\n items = [],\n renderItem,\n label = '<empty>',\n open: shouldOpen,\n onAdd,\n onRemove,\n autoFocusEntry,\n compareFn\n } = props;\n\n const [ open, setOpen ] = useState(!!shouldOpen);\n\n const hasItems = !!items.length;\n const toggleOpen = () => hasItems && setOpen(!open);\n\n const opening = !usePrevious(open) && open;\n const elementChanged = usePrevious(element) !== element;\n const shouldReset = opening || elementChanged;\n const sortedItems = useSortedItems(items, compareFn, shouldReset);\n\n const newItems = useNewItems(items, elementChanged);\n\n useEffect(() => {\n if (open && !hasItems) {\n setOpen(false);\n }\n }, [ open, hasItems ]);\n\n /**\n * @param {MouseEvent} event\n */\n function addItem(event) {\n event.stopPropagation();\n onAdd();\n\n if (!open) {\n setOpen(true);\n }\n }\n\n return (\n <div\n data-entry-id={ id }\n class={ classnames(\n 'bio-properties-panel-entry',\n 'bio-properties-panel-list-entry',\n hasItems ? '' : 'empty',\n open ? 'open' : ''\n ) }>\n <div class=\"bio-properties-panel-list-entry-header\" onClick={ toggleOpen }>\n <div\n title={ label }\n class={ classnames(\n 'bio-properties-panel-list-entry-header-title',\n open && 'open'\n ) }>\n { label }\n </div>\n <div\n class=\"bio-properties-panel-list-entry-header-buttons\"\n >\n <button\n title=\"Create new list item\"\n onClick={ addItem }\n class=\"bio-properties-panel-add-entry\"\n >\n <CreateIcon />\n {\n !hasItems ? (\n <div class=\"bio-properties-panel-add-entry-label\">Create</div>\n )\n : null\n }\n </button>\n {\n hasItems && (\n <div\n title={ `List contains ${items.length} item${items.length != 1 ? 's' : ''}` }\n class=\"bio-properties-panel-list-badge\"\n >\n { items.length }\n </div>\n )\n }\n {\n hasItems && (\n <button\n title=\"Toggle list item\"\n class=\"bio-properties-panel-arrow\"\n >\n <ArrowIcon class={ open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right' } />\n </button>\n )\n }\n </div>\n </div>\n {\n hasItems && (\n <ItemsList\n autoFocusEntry={ autoFocusEntry }\n id={ id }\n open={ open }\n items={ sortedItems }\n newItems={ newItems }\n onRemove={ onRemove }\n renderItem={ renderItem }\n />\n )\n }\n </div>\n );\n}\n\nfunction ItemsList(props) {\n const {\n autoFocusEntry,\n id,\n items,\n newItems,\n open,\n onRemove,\n renderItem\n } = props;\n\n const getKey = useKeyFactory();\n\n const newItem = newItems[0];\n\n useEffect(() => {\n if (newItem && autoFocusEntry) {\n const entry = domQuery(`[data-entry-id=\"${id}\"]`);\n const focusableInput = domQuery('.bio-properties-panel-input', entry);\n\n if (focusableInput) {\n\n if (isFunction(focusableInput.select)) {\n focusableInput.select();\n } else if (isFunction(focusableInput.focus)) {\n focusableInput.focus();\n }\n\n }\n }\n }, [ newItem, autoFocusEntry, id ]);\n\n return (\n <ol class={ classnames(\n 'bio-properties-panel-list-entry-items',\n open ? 'open' : ''\n ) }>\n {\n items.map((item, index) => {\n const key = getKey(item);\n\n return (<li class=\"bio-properties-panel-list-entry-item\" key={ key }>\n { renderItem(item, index, item === newItem) }\n {\n onRemove && (\n <button\n type=\"button\"\n title=\"Delete item\"\n class=\"bio-properties-panel-remove-entry bio-properties-panel-remove-list-entry\"\n onClick={ () => onRemove && onRemove(item) }\n ><DeleteIcon /></button>\n )\n }\n </li>);\n })\n }\n </ol>);\n}\n\n/**\n * Place new items in the beginning of the list and sort the rest with provided function.\n *\n * @template Item\n * @param {Item[]} currentItems\n * @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items\n * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook\n * @returns {Item[]}\n */\nfunction useSortedItems(currentItems, compareFn, shouldReset = false) {\n const itemsRef = useRef(currentItems.slice());\n\n // (1) Reset and optionally sort.\n if (shouldReset) {\n itemsRef.current = currentItems.slice();\n\n if (compareFn) {\n itemsRef.current.sort(compareFn);\n }\n } else {\n const items = itemsRef.current;\n\n // (2) Add new item to the list.\n for (const item of currentItems) {\n if (!items.includes(item)) {\n\n // Unshift or push depending on whether we have a compareFn\n compareFn ? items.unshift(item) : items.push(item);\n }\n }\n\n // (3) Filter out removed items.\n itemsRef.current = items.filter(item => currentItems.includes(item));\n }\n\n return itemsRef.current;\n}\n\nfunction useNewItems(items = [], shouldReset) {\n const previousItems = usePrevious(items.slice()) || [];\n\n if (shouldReset) {\n return [];\n }\n\n return previousItems ? items.filter(item => !previousItems.includes(item)) : [];\n}\n"],"file":"List.js"}
1
+ {"version":3,"sources":["../../../src/components/entries/List.js"],"names":["useEffect","useRef","useState","query","domQuery","isFunction","useKeyFactory","usePrevious","classnames","ArrowIcon","CreateIcon","DeleteIcon","List","props","id","element","items","renderItem","label","open","shouldOpen","onAdd","onRemove","autoFocusEntry","compareFn","setOpen","hasItems","length","toggleOpen","opening","elementChanged","shouldReset","sortedItems","useSortedItems","newItems","useNewItems","addItem","event","stopPropagation","ItemsList","getKey","newItem","entry","selector","focusableInput","select","focus","map","item","index","key","currentItems","itemsRef","slice","current","sort","includes","unshift","push","filter","previousItems"],"mappings":"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","sourcesContent":["import {\n useEffect,\n useRef,\n useState\n} from 'preact/hooks';\n\nimport {\n query as domQuery\n} from 'min-dom';\n\nimport { isFunction } from 'min-dash';\n\nimport {\n useKeyFactory,\n usePrevious\n} from '../../hooks';\n\nimport classnames from 'classnames';\n\nimport {\n ArrowIcon,\n CreateIcon,\n DeleteIcon\n} from '../icons';\n\n/**\n * Entry for handling lists represented as nested entries.\n *\n * @template Item\n * @param {object} props\n * @param {string} props.id\n * @param {*} props.element\n * @param {Function} props.onAdd\n * @param {(item: Item, index: number, isNew: boolean) => JSX.Element} props.renderItem\n * @param {string} [props.label='<empty>']\n * @param {Function} [props.onRemove]\n * @param {Item[]} [props.items]\n * @param {boolean} [props.open]\n * @param {string|boolean} [props.autoFocusEntry] either a custom selector string or true to focus the first input\n * @param {(a: Item, b: Item) => -1 | 0 | 1} [props.compareFn]\n * @returns\n */\nexport default function List(props) {\n const {\n id,\n element,\n items = [],\n renderItem,\n label = '<empty>',\n open: shouldOpen,\n onAdd,\n onRemove,\n autoFocusEntry,\n compareFn\n } = props;\n\n const [ open, setOpen ] = useState(!!shouldOpen);\n\n const hasItems = !!items.length;\n const toggleOpen = () => hasItems && setOpen(!open);\n\n const opening = !usePrevious(open) && open;\n const elementChanged = usePrevious(element) !== element;\n const shouldReset = opening || elementChanged;\n const sortedItems = useSortedItems(items, compareFn, shouldReset);\n\n const newItems = useNewItems(items, elementChanged);\n\n useEffect(() => {\n if (open && !hasItems) {\n setOpen(false);\n }\n }, [ open, hasItems ]);\n\n /**\n * @param {MouseEvent} event\n */\n function addItem(event) {\n event.stopPropagation();\n onAdd();\n\n if (!open) {\n setOpen(true);\n }\n }\n\n return (\n <div\n data-entry-id={ id }\n class={ classnames(\n 'bio-properties-panel-entry',\n 'bio-properties-panel-list-entry',\n hasItems ? '' : 'empty',\n open ? 'open' : ''\n ) }>\n <div class=\"bio-properties-panel-list-entry-header\" onClick={ toggleOpen }>\n <div\n title={ label }\n class={ classnames(\n 'bio-properties-panel-list-entry-header-title',\n open && 'open'\n ) }>\n { label }\n </div>\n <div\n class=\"bio-properties-panel-list-entry-header-buttons\"\n >\n <button\n title=\"Create new list item\"\n onClick={ addItem }\n class=\"bio-properties-panel-add-entry\"\n >\n <CreateIcon />\n {\n !hasItems ? (\n <div class=\"bio-properties-panel-add-entry-label\">Create</div>\n )\n : null\n }\n </button>\n {\n hasItems && (\n <div\n title={ `List contains ${items.length} item${items.length != 1 ? 's' : ''}` }\n class=\"bio-properties-panel-list-badge\"\n >\n { items.length }\n </div>\n )\n }\n {\n hasItems && (\n <button\n title=\"Toggle list item\"\n class=\"bio-properties-panel-arrow\"\n >\n <ArrowIcon class={ open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right' } />\n </button>\n )\n }\n </div>\n </div>\n {\n hasItems && (\n <ItemsList\n autoFocusEntry={ autoFocusEntry }\n id={ id }\n open={ open }\n items={ sortedItems }\n newItems={ newItems }\n onRemove={ onRemove }\n renderItem={ renderItem }\n />\n )\n }\n </div>\n );\n}\n\nfunction ItemsList(props) {\n const {\n autoFocusEntry,\n id,\n items,\n newItems,\n open,\n onRemove,\n renderItem\n } = props;\n\n const getKey = useKeyFactory();\n\n const newItem = newItems[0];\n\n useEffect(() => {\n if (newItem && autoFocusEntry) {\n\n // (0) select the parent entry (containing all list items)\n const entry = domQuery(`[data-entry-id=\"${id}\"]`);\n\n // (1) select the first input or a custom element to be focussed\n const selector = typeof(autoFocusEntry) === 'boolean' ?\n '.bio-properties-panel-input' :\n autoFocusEntry;\n const focusableInput = domQuery(selector, entry);\n\n // (2) set focus\n if (focusableInput) {\n\n if (isFunction(focusableInput.select)) {\n focusableInput.select();\n } else if (isFunction(focusableInput.focus)) {\n focusableInput.focus();\n }\n\n }\n }\n }, [ newItem, autoFocusEntry, id ]);\n\n return (\n <ol class={ classnames(\n 'bio-properties-panel-list-entry-items',\n open ? 'open' : ''\n ) }>\n {\n items.map((item, index) => {\n const key = getKey(item);\n\n return (<li class=\"bio-properties-panel-list-entry-item\" key={ key }>\n { renderItem(item, index, item === newItem) }\n {\n onRemove && (\n <button\n type=\"button\"\n title=\"Delete item\"\n class=\"bio-properties-panel-remove-entry bio-properties-panel-remove-list-entry\"\n onClick={ () => onRemove && onRemove(item) }\n ><DeleteIcon /></button>\n )\n }\n </li>);\n })\n }\n </ol>);\n}\n\n/**\n * Place new items in the beginning of the list and sort the rest with provided function.\n *\n * @template Item\n * @param {Item[]} currentItems\n * @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items\n * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook\n * @returns {Item[]}\n */\nfunction useSortedItems(currentItems, compareFn, shouldReset = false) {\n const itemsRef = useRef(currentItems.slice());\n\n // (1) Reset and optionally sort.\n if (shouldReset) {\n itemsRef.current = currentItems.slice();\n\n if (compareFn) {\n itemsRef.current.sort(compareFn);\n }\n } else {\n const items = itemsRef.current;\n\n // (2) Add new item to the list.\n for (const item of currentItems) {\n if (!items.includes(item)) {\n\n // Unshift or push depending on whether we have a compareFn\n compareFn ? items.unshift(item) : items.push(item);\n }\n }\n\n // (3) Filter out removed items.\n itemsRef.current = items.filter(item => currentItems.includes(item));\n }\n\n return itemsRef.current;\n}\n\nfunction useNewItems(items = [], shouldReset) {\n const previousItems = usePrevious(items.slice()) || [];\n\n if (shouldReset) {\n return [];\n }\n\n return previousItems ? items.filter(item => !previousItems.includes(item)) : [];\n}\n"],"file":"List.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bpmn-io/properties-panel",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Library for creating bpmn-io properties panels.",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -63,7 +63,7 @@
63
63
  "karma-mocha": "^2.0.1",
64
64
  "karma-sinon-chai": "^2.0.2",
65
65
  "karma-webpack": "^5.0.0",
66
- "mocha": "^9.0.0",
66
+ "mocha": "^9.1.3",
67
67
  "mocha-test-container-support": "^0.2.0",
68
68
  "npm-run-all": "^4.1.5",
69
69
  "preact": "^10.5.13",