@pictogrammers/components 0.5.14 → 0.5.17

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.
Files changed (153) hide show
  1. package/package.json +1 -1
  2. package/pg/autocompleteItem/__examples__/basic/basic.html +3 -0
  3. package/pg/autocompleteItem/autocompleteItem.css +55 -0
  4. package/pg/autocompleteItem/autocompleteItem.html +1 -0
  5. package/pg/autocompleteItem/autocompleteItem.ts +65 -0
  6. package/pg/button/button.css +5 -0
  7. package/pg/buttonMenu/buttonMenu.ts +1 -1
  8. package/pg/inputCombobox/__examples__/basic/basic.ts +33 -0
  9. package/pg/inputCombobox/inputCombobox.ts +158 -0
  10. package/pg/inputCombobox/inputCombobox.ts.tmp.44252.751480cb81cc +158 -0
  11. package/pg/inputCombobox/inputCombobox.ts.tmp.44252.dcea847c40a8 +156 -0
  12. package/pg/inputNumber/inputNumber.ts +31 -13
  13. package/pg/inputPill/inputPill.html +6 -0
  14. package/pg/inputPill/inputPill.html.tmp.26852.84ac63f4c46f +6 -0
  15. package/pg/inputPill/inputPill.ts +41 -0
  16. package/pg/inputPills/__examples__/basic/basic.html +9 -0
  17. package/pg/inputPills/__examples__/basic/basic.html.tmp.26852.4771e4cad5b7 +9 -0
  18. package/pg/inputPills/__examples__/basic/basic.ts.tmp.26852.d8fe41df18bd +0 -0
  19. package/pg/inputPixelEditor/README.md +104 -69
  20. package/pg/inputPixelEditor/README.md.tmp.42596.658de5f0a6f5 +0 -0
  21. package/pg/inputPixelEditor/__examples__/basic/basic.ts +6 -5
  22. package/pg/inputPixelEditor/inputPixelEditor.ts +95 -23
  23. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.38516.96529dd82670 +1703 -0
  24. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.42596.48ecc3ad9c72 +1724 -0
  25. package/pg/inputPixelEditor/utils/bitmapToMask.ts +113 -79
  26. package/pg/inputPixelEditor/utils/getLassoPixels.ts +51 -0
  27. package/pg/inputRange/inputRange.css +7 -0
  28. package/pg/inputSelect/__examples__/basic/basic.ts +2 -2
  29. package/pg/inputSelect/inputSelect.css +1 -1
  30. package/pg/inputSelect/inputSelect.ts +62 -5
  31. package/pg/inputText/README.md +6 -6
  32. package/pg/inputText/__examples__/basic/basic.ts +1 -1
  33. package/pg/inputText/inputText.css +2 -2
  34. package/pg/inputText copy/README.md +38 -0
  35. package/pg/inputText copy/inputText.css +41 -0
  36. package/pg/inputText copy/inputText.html +1 -0
  37. package/pg/inputText copy/inputText.spec.ts +59 -0
  38. package/pg/inputText copy/inputText.ts +67 -0
  39. package/pg/inputTextarea/README.md +39 -0
  40. package/pg/inputTextarea/__examples__/basic/basic.html +9 -0
  41. package/pg/inputTextarea/__examples__/basic/basic.ts +30 -0
  42. package/pg/inputTextarea/inputTextarea.ts +121 -0
  43. package/pg/inputTextarea copy/README.md +39 -0
  44. package/pg/inputTextarea copy/inputTextarea.css +41 -0
  45. package/pg/inputTextarea copy/inputTextarea.html +1 -0
  46. package/pg/inputTextarea copy/inputTextarea.spec.ts +59 -0
  47. package/pg/inputTextarea copy/inputTextarea.ts +79 -0
  48. package/pg/inputTextareaAutocomplete/README.md +70 -0
  49. package/pg/inputTextareaAutocomplete/__examples__/basic/basic.ts +67 -0
  50. package/pg/inputTextareaAutocomplete/inputTextareaAutocomplete.ts +267 -0
  51. package/pg/node/README.md +35 -0
  52. package/pg/node/__examples__/basic/basic.ts +34 -0
  53. package/pg/node/index.ts +3 -0
  54. package/pg/node/node.css +53 -0
  55. package/pg/node/node.html +5 -0
  56. package/pg/node/node.ts +270 -0
  57. package/pg/nodeEditorLink/nodeEditorLink.css +69 -0
  58. package/pg/nodeEditorLink/nodeEditorLink.css.tmp.1408.09e961fd0dcc +69 -0
  59. package/pg/nodeEditorLink/nodeEditorLink.html +9 -0
  60. package/pg/nodeEditorNumber/nodeEditorNumber.css +59 -0
  61. package/pg/nodeEditorNumber/nodeEditorNumber.ts +57 -0
  62. package/pg/nodeEditorRange/nodeEditorRange.css +23 -0
  63. package/pg/nodeEditorRange/nodeEditorRange.ts +69 -0
  64. package/pg/nodeEditorText/__examples__/basic/basic.html +9 -0
  65. package/pg/nodeEditorText/__examples__/basic/basic.ts +30 -0
  66. package/pg/nodeEditorText/nodeEditorText.css +17 -0
  67. package/pg/nodeEditorText/nodeEditorText.html +4 -0
  68. package/pg/nodeEditorText/nodeEditorText.ts +57 -0
  69. package/pg/nodeEditorText copy/README.md +35 -0
  70. package/pg/nodeEditorText copy/nodeEditorText.css +49 -0
  71. package/pg/nodeEditorText copy/nodeEditorText.html +4 -0
  72. package/pg/nodeEditorText copy/nodeEditorText.ts +50 -0
  73. package/pg/nodeEditorTextArray/nodeEditorTextArray.css +68 -0
  74. package/pg/nodeEditorTextArray/nodeEditorTextArray.html +9 -0
  75. package/pg/nodeEditorTextArray/nodeEditorTextArray.ts +162 -0
  76. package/pg/nodeEntry/nodeEntry.css +61 -0
  77. package/pg/nodeEntry/nodeEntry.ts +164 -0
  78. package/pg/nodeEntry/nodeEntry.ts.tmp.28724.dda67762bca5 +164 -0
  79. package/pg/nodeInputText/nodeInputText.css +75 -0
  80. package/pg/nodeInputText/nodeInputText.html +4 -0
  81. package/pg/nodeInputText/nodeInputText.ts +105 -0
  82. package/pg/nodeOutput/nodeOutput.css +32 -0
  83. package/pg/nodeResize/README.md +3 -0
  84. package/pg/nodeResize/THINKING.md +81 -0
  85. package/pg/nodeResize/THINKING.md.tmp.24812.99a70ba81062 +81 -0
  86. package/pg/nodeResize/basic/basic.ts +17 -0
  87. package/pg/nodeResize/dragUtil.ts +105 -0
  88. package/pg/nodeResize/dragUtil.ts.tmp.34372.787464c73309 +75 -0
  89. package/pg/nodeResize/nodeResize.css +187 -0
  90. package/pg/nodeResize/nodeResize.html +9 -0
  91. package/pg/nodeResize/nodeResize.ts +156 -0
  92. package/pg/nodes/README.md +177 -0
  93. package/pg/nodes/__examples__/basic/basic.html +33 -0
  94. package/pg/nodes/__examples__/basic/basic.ts +716 -0
  95. package/pg/nodes/__examples__/basic/exampleNodes.ts +129 -0
  96. package/pg/nodes/__examples__/basic/exampleScripts.ts +129 -0
  97. package/pg/nodes/__examples__/basic/keystore.ts +38 -0
  98. package/pg/nodes/executeInSandbox.ts +32 -0
  99. package/pg/nodes/index.ts +3 -0
  100. package/pg/nodes/nodes.css +69 -0
  101. package/pg/nodes/nodes.html +6 -0
  102. package/pg/nodes/nodes.ts +1240 -0
  103. package/pg/nodes copy/nodes.css +41 -0
  104. package/pg/nodes copy/nodes.html +1 -0
  105. package/pg/overlayContextMenu/__examples__/filter/filter.ts +87 -0
  106. package/pg/overlayContextMenu/overlayContextMenu.css +14 -0
  107. package/pg/overlayContextMenu/overlayContextMenu.html +4 -3
  108. package/pg/overlayContextMenu/overlayContextMenu.ts +6 -2
  109. package/pg/overlayContextMenu/overlayContextMenu.ts.tmp.37088.530ff1c0a321 +0 -0
  110. package/pg/overlayMenu/overlayMenu.css +3 -1
  111. package/pg/overlayMenu/overlayMenu.ts +11 -2
  112. package/pg/overlayMenu/overlayMenu.ts.tmp.44252.9bb22fd59ede +80 -0
  113. package/pg/overlaySelectMenu/overlaySelectMenu.css +2 -0
  114. package/pg/overlaySubMenu/overlaySubMenu.css +8 -6
  115. package/pg/poco/README.md +22 -0
  116. package/pg/poco/__examples__/basic/basic.html +11 -0
  117. package/pg/poco/__examples__/basic/basic.ts +95 -0
  118. package/pg/poco/__examples__/basic/examples.ts +258 -0
  119. package/pg/poco/__examples__/basic/myFont.ts +1300 -0
  120. package/pg/poco/index.ts +3 -0
  121. package/pg/poco/mockPoco.ts +640 -0
  122. package/pg/poco/poco.css +7 -0
  123. package/pg/poco/poco.html +1 -0
  124. package/pg/poco/poco.ts +75 -0
  125. package/pg/popover/README.md +47 -0
  126. package/pg/popover/__examples__/basic/basic.html +3 -0
  127. package/pg/popover/popover.html +3 -0
  128. package/pg/popover/popover.ts +44 -0
  129. package/pg/popoverAutocomplete/__examples__/basic/basic.html +4 -0
  130. package/pg/popoverAutocomplete/__examples__/basic/basic.ts +46 -0
  131. package/pg/popoverAutocomplete/popoverAutocomplete.css +25 -0
  132. package/pg/popoverAutocomplete/popoverAutocomplete.html +1 -0
  133. package/pg/popoverAutocomplete/popoverAutocomplete.ts +134 -0
  134. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.css +69 -0
  135. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.ts +90 -0
  136. package/pg/table/__examples__/basic/basic.ts +1 -0
  137. package/pg/tableCellFileLocal/tableCellFileLocal.html +3 -0
  138. package/pg/tableCellFileLocal/tableCellFileLocal.html.tmp.20484.68ee2e30710e +3 -0
  139. package/pg/tableCellFileLocal/tableCellFileLocal.ts +44 -0
  140. package/pg/tableCellSelect/tableCellSelect.html +3 -0
  141. package/pg/tableCellSelect/tableCellSelect.html.tmp.41808.99c1a6f14340 +3 -0
  142. package/pg/tableCellSelect/tableCellSelect.ts +51 -0
  143. package/pg/tree/__examples__/basic/basic.ts +12 -5
  144. package/pg/tree/tree.html +1 -1
  145. package/pg/tree/tree.ts +385 -227
  146. package/pg/tree/tree.ts.tmp.38376.07d376a04f41 +343 -0
  147. package/pg/tree/tree.ts.tmp.38376.2a04599ade9f +361 -0
  148. package/pg/tree/tree.ts.tmp.38376.6cb2c663d476 +0 -0
  149. package/pg/tree/tree.ts.tmp.38376.ac5af1aff2b0 +393 -0
  150. package/pg/tree/tree.ts.tmp.38376.ac9acfc4f95f +324 -0
  151. package/pg/treeItem/treeItem.ts +536 -558
  152. package/pg/treeItem/treeItem.ts.tmp.38376.145d3121d648 +530 -0
  153. package/pg/treeItem/treeItem.ts.tmp.38376.b5224d48e5c0 +0 -0
@@ -0,0 +1,75 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import { MockBitmap, MockPoco, MockResource, MockParseBMP, MockParseBMF } from './mockPoco';
4
+
5
+ import template from './poco.html';
6
+ import style from './poco.css';
7
+ import { FntFont } from '@pictogrammers/fnt/dist/shared';
8
+
9
+ @Component({
10
+ selector: 'pg-poco',
11
+ style,
12
+ template,
13
+ })
14
+ export default class PgPoco extends HTMLElement {
15
+ @Prop() width: number = 400;
16
+ @Prop() height: number = 240;
17
+
18
+ @Part() $canvas: HTMLCanvasElement;
19
+
20
+ #poco: MockPoco;
21
+
22
+ connectedCallback() {
23
+ this.$canvas.width = this.width;
24
+ this.$canvas.height = this.height;
25
+ this.$canvas.style.width = `${this.width}px`;
26
+ this.$canvas.style.height = `${this.height}px`;
27
+ this.#poco = new MockPoco(this.$canvas);
28
+ }
29
+
30
+ get poco() {
31
+ return this.#poco;
32
+ }
33
+
34
+ get Resource() {
35
+ return MockResource;
36
+ }
37
+
38
+ get parseBMP() {
39
+ return MockParseBMP;
40
+ }
41
+
42
+ get parseBMF() {
43
+ return MockParseBMF;
44
+ }
45
+
46
+ setResourceBMP(
47
+ fileName: string,
48
+ buffer: any,
49
+ ) {
50
+ MockResource.setBMP(fileName, MockBitmap.from(buffer));
51
+ }
52
+
53
+ setResourceBMPCanvas(
54
+ fileName: string,
55
+ width: number,
56
+ height: number,
57
+ create: (ctx: CanvasRenderingContext2D, w: number, h: number) => void,
58
+ ) {
59
+ MockResource.setBMP(fileName, MockBitmap.create(width, height, create));
60
+ }
61
+
62
+ setResourceBMF(
63
+ fileName: string,
64
+ buffer: ArrayBuffer | Uint8Array<ArrayBufferLike>,
65
+ ) {
66
+ MockResource.setBMF(fileName, buffer);
67
+ }
68
+
69
+ setResourceBMFJSON(
70
+ fileName: string,
71
+ json: FntFont,
72
+ ) {
73
+ MockResource.setBMFJSON(fileName, json);
74
+ }
75
+ }
@@ -0,0 +1,47 @@
1
+ # `PgPopover`
2
+
3
+ The `PgPopover` class provides a way to create a non-modal element on the body element. Unlike `PgOverlay`, `PgPopover` does not trap focus and `create` returns the created instance directly rather than a Promise.
4
+
5
+ Elements that should be attached at the body root without blocking interaction (tooltips, dropdowns, context menus) should extend `PgPopover`.
6
+
7
+ | Method | Description |
8
+ | ------ | ----------- |
9
+ | `destroy()` | Destroy |
10
+ | `hide()` | Hide |
11
+ | `show()` | Show |
12
+
13
+ ## Example Tooltip
14
+
15
+ ```typescript
16
+ import { Component, Prop } from '@pictogrammers/element';
17
+ import PgPopover from '@pictogrammers/components/pgPopover';
18
+
19
+ import template from './tooltip.html';
20
+ import style from './tooltip.css';
21
+
22
+ @Component({
23
+ selector: 'my-tooltip',
24
+ template,
25
+ style
26
+ })
27
+ export default class MyTooltip extends PgPopover {
28
+ // This will render attached to the body.
29
+ // To close call this.close();
30
+
31
+ @Prop() message: string = '';
32
+ }
33
+ ```
34
+
35
+ The `create` method creates an instance, attaches it to the `<body>` tag, and returns it synchronously.
36
+
37
+ ```typescript
38
+ import MyTooltip from './../tooltip/tooltip';
39
+
40
+ const tooltip = PgTooltip.create({
41
+ source: this.$trigger,
42
+ message: 'Hello!',
43
+ });
44
+
45
+ // Later, dismiss it:
46
+ tooltip.destroy();
47
+ ```
@@ -0,0 +1,3 @@
1
+ <div class="example">
2
+ <p>Extend <code>PgPopover</code> to create popovers. View the readme for details.</p>
3
+ </div>
@@ -0,0 +1,3 @@
1
+ <div part="popover" popover="manual">
2
+ <child/>
3
+ </div>
@@ -0,0 +1,44 @@
1
+ import { Component, Part, Prop } from '@pictogrammers/element';
2
+
3
+ import template from './popover.html';
4
+
5
+ const layers: Set<HTMLElement> = new Set();
6
+
7
+ type OmitByPrefix<T, Prefix extends string> = {
8
+ [K in keyof T as K extends `${Prefix}${string}` ? never : K]: T[K];
9
+ };
10
+
11
+ @Component({
12
+ template,
13
+ })
14
+ export default class PgPopover extends HTMLElement {
15
+ static create<T extends typeof PgPopover>(this: T, props: Partial<OmitByPrefix<Omit<InstanceType<T>, Exclude<keyof PgPopover, 'source'>>, '$'>>): InstanceType<T> {
16
+ var ele = document.createElement(this.name) as InstanceType<T>;
17
+ props && Object.assign(ele, props);
18
+ document.body.appendChild(ele);
19
+ layers.add(ele);
20
+ return ele;
21
+ }
22
+
23
+ @Prop() source: HTMLElement | null = null;
24
+
25
+ @Part() $popover: PgPopover;
26
+
27
+ visible = false;
28
+
29
+ hide() {
30
+ this.$popover.hidePopover();
31
+ this.visible = false;
32
+ }
33
+
34
+ show() {
35
+ // @ts-ignore
36
+ this.$popover.showPopover({ source: this.source });
37
+ this.visible = true;
38
+ }
39
+
40
+ destroy() {
41
+ this.remove();
42
+ layers.delete(this);
43
+ }
44
+ }
@@ -0,0 +1,4 @@
1
+ <div class="example">
2
+ <input type="text" part="trigger" placeholder="Type a fruit" />
3
+ <p>Selected: <span part="result">none</span></p>
4
+ </div>
@@ -0,0 +1,46 @@
1
+ import { Component, Part } from '@pictogrammers/element';
2
+
3
+ import PgPopoverAutocomplete from '../../popoverAutocomplete';
4
+
5
+ import template from './basic.html';
6
+ import style from './basic.css';
7
+
8
+ @Component({
9
+ selector: 'x-pg-popover-autocomplete-basic',
10
+ template,
11
+ style,
12
+ })
13
+ export default class XPgPopoverAutocompleteBasic extends HTMLElement {
14
+ @Part() $trigger: HTMLButtonElement;
15
+ @Part() $result: HTMLSpanElement;
16
+
17
+ #popover: PgPopoverAutocomplete | null = null;
18
+
19
+ connectedCallback() {
20
+ this.$trigger.addEventListener('focus', () => {
21
+ if (this.#popover) {
22
+ this.#popover.show();
23
+ return;
24
+ };
25
+ this.#popover = PgPopoverAutocomplete.create({
26
+ source: this.$trigger,
27
+ items: [
28
+ { label: 'Apple', value: 'apple' },
29
+ { label: 'Banana', value: 'banana' },
30
+ { label: 'Cherry', value: 'cherry' },
31
+ { label: 'Grape', value: 'grape' },
32
+ { label: 'Mango', value: 'mango' },
33
+ ],
34
+ });
35
+ this.#popover.show();
36
+ this.#popover.addEventListener('select', (e: any) => {
37
+ const { label, value } = e.detail;
38
+ this.$result.textContent = `${label} (${value})`;
39
+ });
40
+ this.#popover.addEventListener('dismiss', () => {
41
+ this.#popover?.destroy();
42
+ this.#popover = null;
43
+ }, { once: true });
44
+ });
45
+ }
46
+ }
@@ -0,0 +1,25 @@
1
+ :host {
2
+ display: contents;
3
+ }
4
+
5
+ [part="popover"] {
6
+ margin: 0;
7
+ padding: 0;
8
+ border: 0;
9
+ background: transparent;
10
+ top: calc(anchor(bottom) - 1px);
11
+ left: anchor(left);
12
+ min-width: anchor-size(width);
13
+ overflow: visible;
14
+ }
15
+
16
+ [part="items"] {
17
+ display: flex;
18
+ flex-direction: column;
19
+ border-width: var(--pg-autocomplete-border-width, 1px);
20
+ border-color: var(--pg-autocomplete-border-color, #453C4F);
21
+ border-style: solid;
22
+ border-radius: 0.25rem;
23
+ background-color: var(--pg-autocomplete-background-color, #FFFFFF);
24
+ box-shadow: var(--pg-autocomplete-box-shadow, 0 0.125rem 0.5rem rgba(0, 0, 0, 0.25));
25
+ }
@@ -0,0 +1 @@
1
+ <div part="items"></div>
@@ -0,0 +1,134 @@
1
+ import { Component, Prop, Part, forEach } from '@pictogrammers/element';
2
+
3
+ import PgPopover from '../popover/popover';
4
+ import PgPopoverAutocompleteItem from '../popoverAutocompleteItem/popoverAutocompleteItem';
5
+
6
+ import template from './popoverAutocomplete.html';
7
+ import style from './popoverAutocomplete.css';
8
+
9
+ @Component({
10
+ selector: 'pg-popover-autocomplete',
11
+ style,
12
+ template
13
+ })
14
+ export default class PgPopoverAutocomplete extends PgPopover {
15
+ @Part() $items: HTMLDivElement;
16
+
17
+ @Prop() items: { label: string; value: string }[] = [];
18
+
19
+ #index: number = -1;
20
+ #ignore: boolean = false;
21
+
22
+ connectedCallback() {
23
+ forEach({
24
+ container: this.$items,
25
+ items: this.items,
26
+ type: () => PgPopoverAutocompleteItem,
27
+ create: ($item: PgPopoverAutocompleteItem, _item: { label: string; value: string }) => {
28
+ $item.addEventListener('ignore', (e: any) => {
29
+ this.#ignore = true;
30
+ this.#focusItem(e.detail.index);
31
+ });
32
+ $item.addEventListener('select', (e: any) => {
33
+ this.dispatchEvent(new CustomEvent('select', { detail: e.detail }));
34
+ this.hide();
35
+ this.#ignore = false;
36
+ });
37
+ $item.addEventListener('left', (e: any) => {
38
+ this.dispatchEvent(new CustomEvent('dismiss'));
39
+ });
40
+ $item.addEventListener('right', (e: any) => {
41
+ this.dispatchEvent(new CustomEvent('dismiss'));
42
+ });
43
+ $item.addEventListener('up', (e: any) => {
44
+ this.#focusItem(e.detail.index - 1);
45
+ });
46
+ $item.addEventListener('down', (e: any) => {
47
+ this.#focusItem(e.detail.index + 1);
48
+ });
49
+ $item.addEventListener('close', () => {
50
+ this.hide();
51
+ this.source?.focus();
52
+ });
53
+ }
54
+ });
55
+
56
+ this.$popover.addEventListener('toggle', this.#toggle.bind(this));
57
+
58
+ this.#focusItem(0);
59
+ }
60
+
61
+ render(changes) {
62
+ if (changes.source) {
63
+ this.source?.addEventListener('keydown', this.handleKeydown);
64
+ this.source?.addEventListener('blur', this.handleBlur);
65
+ }
66
+ }
67
+
68
+ handleBlur = (e: FocusEvent) => {
69
+ if (this.#ignore) {
70
+ return;
71
+ }
72
+ this.hide();
73
+ }
74
+
75
+ handleKeydown = (e: KeyboardEvent) => {
76
+ switch(e.key) {
77
+ case 'Tab':
78
+ this.dispatchEvent(new CustomEvent('dismiss'));
79
+ break;
80
+ case 'ArrowUp':
81
+ this.#focusItem(this.#index - 1);
82
+ e.preventDefault();
83
+ break;
84
+ case 'ArrowDown':
85
+ if (this.visible) {
86
+ this.#focusItem(this.#index + 1);
87
+ } else {
88
+ // recreate autocomplete
89
+ }
90
+ e.preventDefault();
91
+ break;
92
+ case 'Enter':
93
+ const item = this.$items.children[this.#index] as any;
94
+ item?.click();
95
+ e.preventDefault();
96
+ break;
97
+ case 'Escape':
98
+ this.hide();
99
+ e.preventDefault();
100
+ break;
101
+ }
102
+ }
103
+
104
+ #toggle(e: ToggleEvent) {
105
+ if (e.newState === 'closed') {
106
+ this.dispatchEvent(new CustomEvent('dismiss'));
107
+ }
108
+ }
109
+
110
+ #focusItem(index: number) {
111
+ //if (index === initIndex) return;
112
+ //if (index < 0) return this.#focusItem(this.items.length - 1, fallback, initIndex);
113
+ //if (index >= this.items.length) return this.#focusItem(0, fallback, initIndex);
114
+ if (this.#index === index) {
115
+ return;
116
+ }
117
+ if (index < 0) {
118
+ index = this.items.length - 1;
119
+ }
120
+ if (index >= this.items.length) {
121
+ index = 0;
122
+ }
123
+ const item = this.$items.children[index] as any;
124
+ item?.focus();
125
+ const previous = this.$items.children[this.#index] as any;
126
+ previous?.blur();
127
+ this.#index = index;
128
+ }
129
+
130
+ disconnectedCallback() {
131
+ this.source?.removeEventListener('keydown', this.handleKeydown);
132
+ }
133
+
134
+ }
@@ -0,0 +1,69 @@
1
+ :host {
2
+ display: contents;
3
+ }
4
+
5
+ [part=label] {
6
+ outline: none;
7
+ display: flex;
8
+ align-items: center;
9
+ font-family: var(--pg-font-family, system-ui);
10
+ text-align: var(--pg-popover-autocomplete-item-text-align, left);
11
+ background-color: var(--pg-popover-autocomplete-item-background, transparent);
12
+ padding: var(--pg-popover-autocomplete-item-padding, 0.125rem 0.25rem);
13
+ border-color: transparent;
14
+ border-width: 0;
15
+ border-style: solid;
16
+ color: var(--pg-popover-autocomplete-item-color, #453C4F);
17
+ width: 100%;
18
+ cursor: pointer;
19
+ }
20
+
21
+ :host(:first-child) [part=label] {
22
+ border-top-left-radius: var(--pg-popover-autocomplete-item-border-radius, 0.125rem);
23
+ border-top-right-radius: var(--pg-popover-autocomplete-item-border-radius, 0.125rem);
24
+ }
25
+
26
+ :host(:last-child) [part=label] {
27
+ border-top-left-radius: var(--pg-popover-autocomplete-item-border-radius, 0.125rem);
28
+ border-top-right-radius: var(--pg-popover-autocomplete-item-border-radius, 0.125rem);
29
+ }
30
+
31
+ [part=label]:not(:disabled):not(.focus):hover {
32
+ background: var(--pg-popover-autocomplete-hover-background-color, rgba(79, 143, 249, 0.1));
33
+ }
34
+
35
+ [part=label]:not(:disabled):active {
36
+ background-color: var(--pg-popover-autocomplete-item-active-background, #5f516e);
37
+ color: #FFFFFF;
38
+ }
39
+
40
+ [part=label]:disabled {
41
+ color: var(--pg-popover-autocomplete-item-disabled-color, rgba(69, 60, 79, 0.75));
42
+ cursor: default;
43
+ }
44
+
45
+ [part=label]:focus-visible {
46
+ position: relative;
47
+ }
48
+
49
+ [part=label]:focus-visible::after {
50
+ pointer-events: none;
51
+ content: '';
52
+ position: absolute;
53
+ top: -1px;
54
+ right: -1px;
55
+ bottom: -1px;
56
+ left: -1px;
57
+ border-radius: var(--pg-popover-autocomplete-item-border-radius, 0.25rem);
58
+ box-shadow: 0 0 0 3px var(--pg-focus-color, rgba(79, 143, 249, 0.5));
59
+ }
60
+
61
+ [part=label].focus {
62
+ background-color: var(--pg-focus-background-color, #453C4F);
63
+ color: #FFFFFF;
64
+ }
65
+
66
+ [part=label]:active {
67
+ background-color: var(--pg-focus-background-color, #453C4F) !important;
68
+ color: #FFFFFF;
69
+ }
@@ -0,0 +1,90 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import template from './popoverAutocompleteItem.html';
4
+ import style from './popoverAutocompleteItem.css';
5
+
6
+ @Component({
7
+ selector: 'pg-popover-autocomplete-item',
8
+ style,
9
+ template
10
+ })
11
+ export default class PgPopoverAutocompleteItem extends HTMLElement {
12
+ static delegatesFocus = true;
13
+
14
+ @Prop() index: number;
15
+ @Prop() label: string = '';
16
+ @Prop() value: any = null;
17
+ @Prop() disabled: boolean = false;
18
+
19
+ @Part() $label: HTMLButtonElement;
20
+
21
+ render(changes) {
22
+ if (changes.label) {
23
+ this.$label.textContent = this.label;
24
+ }
25
+ if (changes.disabled) {
26
+ this.$label.disabled = this.disabled;
27
+ }
28
+ }
29
+
30
+ connectedCallback() {
31
+ this.$label.addEventListener('mousedown', () => {
32
+ this.dispatchEvent(new CustomEvent('ignore', {
33
+ detail: { index: this.index }
34
+ }));
35
+ });
36
+ this.$label.addEventListener('click', () => {
37
+ this.dispatchEvent(new CustomEvent('select', {
38
+ detail: { index: this.index, label: this.label, value: this.value }
39
+ }));
40
+ });
41
+ this.$label.addEventListener('keydown', (e: KeyboardEvent) => {
42
+ switch (e.key) {
43
+ case 'ArrowDown':
44
+ this.dispatchEvent(new CustomEvent('down', {
45
+ detail: { index: this.index }
46
+ }));
47
+ e.preventDefault();
48
+ break;
49
+ case 'ArrowUp':
50
+ this.dispatchEvent(new CustomEvent('up', {
51
+ detail: { index: this.index }
52
+ }));
53
+ e.preventDefault();
54
+ break;
55
+ case 'ArrowLeft':
56
+ this.dispatchEvent(new CustomEvent('left', {
57
+ detail: { index: this.index }
58
+ }));
59
+ e.preventDefault();
60
+ break;
61
+ case 'ArrowRight':
62
+ this.dispatchEvent(new CustomEvent('right', {
63
+ detail: { index: this.index }
64
+ }));
65
+ e.preventDefault();
66
+ break;
67
+ case 'Escape':
68
+ this.dispatchEvent(new CustomEvent('close'));
69
+ e.preventDefault();
70
+ break;
71
+ }
72
+ });
73
+ }
74
+
75
+ click() {
76
+ this.$label.click();
77
+ }
78
+
79
+ focus() {
80
+ this.$label.classList.toggle('focus', true);
81
+ }
82
+
83
+ blur() {
84
+ this.$label.classList.toggle('focus', false);
85
+ }
86
+
87
+ getHeight(): number {
88
+ return this.$label.getBoundingClientRect().height;
89
+ }
90
+ }
@@ -91,6 +91,7 @@ export default class XPgTableBasic extends HTMLElement {
91
91
  newCount = 0;
92
92
  handlePushData() {
93
93
  this.$table.data.push(createTableItem({
94
+ selected: false,
94
95
  name: `new ${this.newCount++}`,
95
96
  age: this.newCount,
96
97
  favorite: {
@@ -0,0 +1,3 @@
1
+ <div part="cell">
2
+ <pg-input-file-local part="input"></pg-input-file-local>
3
+ </div>
@@ -0,0 +1,3 @@
1
+ <div part="cell">
2
+ <pg-input-file-local part="input"></pg-input-file-local>
3
+ </div>
@@ -0,0 +1,44 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import PgInputFileLocal from '../inputFileLocal/inputFileLocal';
4
+
5
+ import template from './tableCellFileLocal.html';
6
+ import style from './tableCellFileLocal.css';
7
+
8
+ @Component({
9
+ selector: 'pg-table-cell-file-local',
10
+ style,
11
+ template
12
+ })
13
+ export default class PgTableCellFileLocal extends HTMLElement {
14
+ @Prop() value: any = null;
15
+ @Prop() key: string = '';
16
+ @Prop() acceptsFileType: string = '';
17
+
18
+ @Part() $input: PgInputFileLocal;
19
+
20
+ #initialized: boolean = false;
21
+
22
+ connectedCallback() {
23
+ // Reconnects re-invoke connectedCallback; guard against duplicate listeners.
24
+ if (this.#initialized) return;
25
+ this.#initialized = true;
26
+ this.$input.addEventListener('change', (e: any) => {
27
+ this.dispatchEvent(
28
+ new CustomEvent('action', {
29
+ detail: {
30
+ value: e.detail.value,
31
+ name: e.detail.name,
32
+ event: 'change',
33
+ }
34
+ })
35
+ );
36
+ });
37
+ }
38
+
39
+ render(changes) {
40
+ if (changes.acceptsFileType) {
41
+ this.$input.acceptsFileType = this.acceptsFileType;
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,3 @@
1
+ <div part="cell">
2
+ <pg-input-select part="input"></pg-input-select>
3
+ </div>
@@ -0,0 +1,3 @@
1
+ <div part="cell">
2
+ <pg-input-select part="input"></pg-input-select>
3
+ </div>
@@ -0,0 +1,51 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import PgInputSelect from '../inputSelect/inputSelect';
4
+
5
+ import template from './tableCellSelect.html';
6
+ import style from './tableCellSelect.css';
7
+
8
+ @Component({
9
+ selector: 'pg-table-cell-select',
10
+ style,
11
+ template
12
+ })
13
+ export default class PgTableCellSelect extends HTMLElement {
14
+ @Prop() value: string = '';
15
+ @Prop() key: string = '';
16
+ @Prop() editable: boolean = false;
17
+ @Prop() options: any[] = [];
18
+
19
+ @Part() $input: PgInputSelect;
20
+
21
+ #initialized: boolean = false;
22
+
23
+ connectedCallback() {
24
+ // Reconnects re-invoke connectedCallback; guard against duplicate listeners.
25
+ if (this.#initialized) return;
26
+ this.#initialized = true;
27
+ this.$input.addEventListener('change', (e: any) => {
28
+ this.dispatchEvent(
29
+ new CustomEvent('action', {
30
+ detail: {
31
+ value: e.detail.value,
32
+ event: 'change',
33
+ }
34
+ })
35
+ );
36
+ });
37
+ }
38
+
39
+ render(changes) {
40
+ // options before value; the label is resolved from options when value is set
41
+ if (changes.options) {
42
+ this.$input.options = this.options;
43
+ }
44
+ if (changes.value) {
45
+ this.$input.value = this.value;
46
+ }
47
+ if (changes.editable) {
48
+ this.$input.readOnly = !this.editable;
49
+ }
50
+ }
51
+ }