cedro 0.1.8 → 0.1.10

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 (79) hide show
  1. package/README.md +7 -4
  2. package/dist/cedro-logo.png +0 -0
  3. package/dist/fangio.jpg +0 -0
  4. package/package.json +4 -2
  5. package/src/core/application.builder.tsx +121 -0
  6. package/src/core/{application.core.ts → application.core.tsx} +175 -9
  7. package/src/core/themes.core.ts +160 -1
  8. package/src/core/uid.ts +3 -3
  9. package/src/index.ts +1 -1
  10. package/src/interfaces/application.interface.ts +10 -3
  11. package/src/interfaces/widget.interface.ts +6 -1
  12. package/src/types/select.item.type.ts +11 -0
  13. package/src/ui/Icon.ui.tsx +158 -0
  14. package/src/ui/IconButton.ui.tsx +233 -0
  15. package/src/ui/{textbox.ui.ts → Textbox.ui.tsx} +69 -8
  16. package/src/ui/accordion.ui.tsx +152 -0
  17. package/src/ui/button.ui.tsx +209 -0
  18. package/src/ui/buttonColor.ui.tsx +87 -0
  19. package/src/ui/buttonmenu.ui.tsx +134 -0
  20. package/src/ui/{buttonstack.ui.ts → buttonstack.ui.tsx} +67 -1
  21. package/src/ui/checkbox.ui.tsx +43 -0
  22. package/src/ui/container.ui.tsx +141 -0
  23. package/src/ui/datagrid.ui.tsx +518 -0
  24. package/src/ui/dialog.tsx +143 -56
  25. package/src/ui/{hpanel.ui.ts → hpanel.ui.tsx} +64 -1
  26. package/src/ui/iconButtonMenu.ui.tsx +176 -0
  27. package/src/ui/image.ui.tsx +123 -0
  28. package/src/ui/index.ts +9 -9
  29. package/src/ui/label.ui.tsx +184 -0
  30. package/src/ui/loading.ui.ts +10 -10
  31. package/src/ui/menu.ui.ts +2 -2
  32. package/src/ui/progressbar.ui.tsx +135 -0
  33. package/src/ui/radiobutton.ui.tsx +47 -0
  34. package/src/ui/scroll.ui.ts +13 -12
  35. package/src/ui/select.ui.tsx +143 -0
  36. package/src/ui/styles/button.css +114 -32
  37. package/src/ui/styles/buttoncolor.css +8 -8
  38. package/src/ui/styles/container.css +29 -0
  39. package/src/ui/styles/hpanel.css +1 -1
  40. package/src/ui/styles/icon.css +29 -0
  41. package/src/ui/styles/image.css +19 -19
  42. package/src/ui/styles/label.css +63 -0
  43. package/src/ui/styles/loading.css +12 -12
  44. package/src/ui/styles/main.css +5 -0
  45. package/src/ui/styles/progressbar.css +3 -2
  46. package/src/ui/styles/select.css +13 -0
  47. package/src/ui/styles/stackbutton.css +36 -0
  48. package/src/ui/styles/tabs.css +5 -7
  49. package/src/ui/styles/textarea.css +13 -13
  50. package/src/ui/styles/valuebar.css +1 -1
  51. package/src/ui/styles/vpanel.css +1 -1
  52. package/src/ui/switch.ui.tsx +42 -0
  53. package/src/ui/{tabs.ui.ts → tabs.ui.tsx} +114 -8
  54. package/src/ui/textarea.ui.tsx +48 -0
  55. package/src/ui/{toolbar.ui.ts → toolbar.ui.tsx} +44 -1
  56. package/src/ui/{valuebar.ui.ts → valuebar.ui.tsx} +35 -1
  57. package/src/ui/{vpanel.ui.ts → vpanel.ui.tsx} +44 -1
  58. package/src/ui/widget.builder.ts +243 -0
  59. package/src/ui/widget.collection.ts +57 -5
  60. package/src/ui/widget.ui.ts +176 -24
  61. package/src/ui/Icon.ui.ts +0 -64
  62. package/src/ui/IconButton.ui.ts +0 -114
  63. package/src/ui/accordion.ui.ts +0 -71
  64. package/src/ui/button.ui.ts +0 -105
  65. package/src/ui/buttonColor.ui.ts +0 -24
  66. package/src/ui/buttonmenu.ui.ts +0 -59
  67. package/src/ui/checkbox.ui.ts +0 -8
  68. package/src/ui/container.ui.ts +0 -38
  69. package/src/ui/datagrid.ui.ts +0 -231
  70. package/src/ui/iconButtonMenu.ui.ts +0 -59
  71. package/src/ui/image.ui.ts +0 -49
  72. package/src/ui/label.ui.ts +0 -82
  73. package/src/ui/progressbar.ui.ts +0 -74
  74. package/src/ui/radiobutton.ts +0 -8
  75. package/src/ui/select.ui.ts +0 -73
  76. package/src/ui/switch.ui.ts +0 -7
  77. package/src/ui/textarea.ui.ts +0 -20
  78. package/src/ui/widget.builder.ui.tsx +0 -676
  79. /package/src/ui/{toggle.ui.ts → toggle.ui.tsx} +0 -0
@@ -0,0 +1,152 @@
1
+ import "./styles/accordion.css";
2
+ import { IconButton } from "./IconButton.ui";
3
+ import { Label } from "./label.ui";
4
+ import { Widget, WidgetTypes } from "./widget.ui";
5
+ import { createWidget, normalizeWidget, WidgetProps } from "./widget.builder";
6
+ import { UID } from "../core/uid";
7
+
8
+ const ACCORDION_HEADER_HEIGHT = 40;
9
+
10
+ type AccordionItem = {
11
+ header: Widget;
12
+ content: Widget;
13
+ };
14
+
15
+ export class Accordion extends Widget {
16
+ items: Map<string, AccordionItem>;
17
+ selectedItemId: string | null;
18
+ constructor(id: string, parent: Widget | null = null) {
19
+ super(id, "div", parent);
20
+
21
+ this.items = new Map<string, AccordionItem>();
22
+
23
+ this.selectedItemId = null;
24
+
25
+ this.addClass("WUIAccordion");
26
+ }
27
+
28
+ public selectItem(id: string): void {
29
+ this.fixItemsType();
30
+
31
+ const selected = this.items.get(id);
32
+
33
+ if (this.selectedItemId !== null) {
34
+ //deseleccionamos
35
+ const previous = this.items.get(this.selectedItemId);
36
+
37
+ if (previous) {
38
+ previous.content.setFixedSize(0);
39
+ }
40
+ }
41
+
42
+ if (selected) {
43
+ this.selectedItemId = id;
44
+ selected.content.setFixedSize(null);
45
+ }
46
+
47
+ this.render();
48
+ }
49
+
50
+ private fixItemsType(): void {
51
+ this.items.forEach((item) => {
52
+ item.header.deleteClass("WUIFixPosition");
53
+ item.header.addClass("WUINonFreePosition");
54
+ item.content.deleteClass("WUIFixPosition");
55
+ item.content.addClass("WUINonFreePosition");
56
+ });
57
+ }
58
+
59
+ public addItem(title: string, icon: string, content: Widget): string {
60
+ const headerId = this.id + ".item." + Array.from(this.items.entries()).length + ".header";
61
+ const header = icon !== "" ? new IconButton(headerId, icon) : new Label(headerId);
62
+
63
+ header.setType(WidgetTypes.FILL);
64
+ header.setFixedSize(ACCORDION_HEADER_HEIGHT);
65
+ header.setText(title);
66
+
67
+ header.deleteClass("WUIFixPosition");
68
+ header.addClass("WUINonFreePosition");
69
+
70
+ header.subscribe({
71
+ event: "click",
72
+ then: (_e, _w) => {
73
+ this.selectItem(headerId);
74
+ },
75
+ });
76
+
77
+ content.setType(WidgetTypes.FILL);
78
+ content.setFixedSize(0);
79
+
80
+ this.items.set(headerId, { header, content });
81
+
82
+ this.addChild(header);
83
+ this.addChild(content);
84
+
85
+ return headerId;
86
+ }
87
+ }
88
+
89
+ export type WAccordionProps = WidgetProps & {
90
+ children: any;
91
+ };
92
+
93
+ export type WAccordionItemProps = {
94
+ title?: string | null;
95
+ icon?: string | null;
96
+ children: any;
97
+ };
98
+
99
+ export const WAccordion = (props: WAccordionProps) => {
100
+ if (!props.id) {
101
+ props.id = "Accordion." + UID();
102
+ }
103
+
104
+ return normalizeWidget(
105
+ <div id={props.id} w-accordion>
106
+ {props.children}
107
+ </div>,
108
+ props
109
+ );
110
+ };
111
+
112
+ export const WAccordionItem = (props: WAccordionItemProps) => {
113
+ return (
114
+ <div w-accordion-item w-title={props.title} w-icon={props.icon}>
115
+ {props.children}
116
+ </div>
117
+ );
118
+ };
119
+
120
+ export function createAccordion(id: string, content: any, parent: Widget | null = null): Accordion {
121
+ let newAccordion = new Accordion(id, parent);
122
+ let firstWidgetId = "";
123
+
124
+ content.childNodes.forEach((accordionItem: HTMLElement, _index: number) => {
125
+ if (accordionItem.getAttribute("w-accordion-item") !== null) {
126
+ const accordionTitle = accordionItem.getAttribute("w-title");
127
+ const accordionIcon = accordionItem.getAttribute("w-icon");
128
+
129
+ if (!accordionItem.firstChild) {
130
+ throw new Error("Accordion Item must have a content");
131
+ }
132
+
133
+ const widget = createWidget(accordionItem.firstChild);
134
+
135
+ if (widget !== null) {
136
+ const itemId = newAccordion.addItem(
137
+ accordionTitle || "Untitled",
138
+ accordionIcon || "",
139
+ widget
140
+ );
141
+
142
+ if (firstWidgetId === "") {
143
+ firstWidgetId = itemId;
144
+ }
145
+ }
146
+ }
147
+ });
148
+
149
+ newAccordion.selectItem(firstWidgetId);
150
+
151
+ return newAccordion;
152
+ }
@@ -0,0 +1,209 @@
1
+ import "./styles/button.css";
2
+ import "./styles/stackbutton.css";
3
+ import "./styles/vstackbutton.css";
4
+ import { Colors } from "./colors.ui";
5
+ import { Widget, WidgetTypes, connectWidgetCallback, getOnlyEventProps } from "./widget.ui";
6
+ import { normalizeWidget, WidgetProps } from "./widget.builder";
7
+ import { UID } from "../core/uid";
8
+
9
+ export type ButonVariants =
10
+ | "contained"
11
+ | "outlined"
12
+ | "text"
13
+ | "stack-start"
14
+ | "stack-middle"
15
+ | "stack-end"
16
+ | "stack-start-active"
17
+ | "stack-middle-active"
18
+ | "stack-end-active"
19
+ | "stack-vertical-start"
20
+ | "stack-vertical-middle"
21
+ | "stack-vertical-end"
22
+ | "stack-vertical-start-active"
23
+ | "stack-vertical-middle-active"
24
+ | "stack-vertical-end-active";
25
+ export type ButonSizes = "small" | "medium" | "large";
26
+
27
+ export class Button extends Widget {
28
+ variant: ButonVariants;
29
+ color: Colors;
30
+ fullWidth: boolean;
31
+ minWidth: boolean;
32
+ size: ButonSizes;
33
+ href: string;
34
+ text: string;
35
+ requiredWidth: number;
36
+
37
+ constructor(id: string, parent: Widget | null = null) {
38
+ super(id, "button", parent);
39
+
40
+ this.requiredWidth = -1;
41
+
42
+ this.fullWidth = false;
43
+ this.minWidth = false;
44
+ //this.setType(WidgetTypes.CUSTOM);
45
+ this.variant = "text";
46
+ this.color = "primary"; //primary";
47
+ this.size = "medium";
48
+ this.href = "#";
49
+ this.text = "";
50
+
51
+ this.configureStyles();
52
+
53
+ this.init();
54
+ }
55
+
56
+ private configureStyles(): void {
57
+ this.deleteAllClasses();
58
+ this.addClass(`WUIButton-${this.variant}`);
59
+ this.addClass(`WUIButton-${this.variant}-color-${this.color}`);
60
+ if (this.type === WidgetTypes.FILL) {
61
+ this.addClass("WUINonFreePosition");
62
+ } else if (this.type === WidgetTypes.CUSTOM) {
63
+ this.addClass("WUINonFreePosition");
64
+ } else if (this.type === WidgetTypes.FREE) {
65
+ this.addClass("WUIFixPosition");
66
+ }
67
+ this.updateRequiredWidth();
68
+ }
69
+
70
+ protected updateRequiredWidth(): void {
71
+ const div = document.createElement("div");
72
+ div.id = this.id + ".requiredWidth";
73
+ div.innerHTML = this.text;
74
+ div.classList.add(`WUIButton-${this.variant}`);
75
+ div.classList.add(`WUIButton-${this.variant}-color-${this.color}`);
76
+ div.style.position = "absolute";
77
+ div.style.overflow = "hidden";
78
+ document.body.appendChild(div);
79
+ this.requiredWidth = div.clientWidth;
80
+ div.parentNode?.removeChild(div);
81
+ }
82
+
83
+ public init(): void {
84
+ super.init();
85
+ }
86
+
87
+ public setText(text: string): void {
88
+ this.text = text;
89
+ this.body.innerHTML = text;
90
+ this.updateRequiredWidth();
91
+ }
92
+
93
+ public setVariant(variant: ButonVariants = "contained"): void {
94
+ this.variant = variant;
95
+ this.configureStyles();
96
+ }
97
+
98
+ public setColor(color: Colors = "primary"): void {
99
+ this.color = color;
100
+ this.configureStyles();
101
+ }
102
+
103
+ public setFullWidth(fullWidth: boolean = false): void {
104
+ this.fullWidth = fullWidth;
105
+ }
106
+
107
+ public setMinWidth(minWidth: boolean = false): void {
108
+ this.minWidth = minWidth;
109
+ if (this.minWidth) {
110
+ if (this.requiredWidth > 0) {
111
+ console.log("cambiando tamano:", this.requiredWidth, " id:", this.id);
112
+ this.setW(this.requiredWidth);
113
+ }
114
+ }
115
+ }
116
+
117
+ public setSize(size: ButonSizes = "medium"): void {
118
+ this.size = size;
119
+ }
120
+
121
+ setHref(href: string): void {
122
+ this.href = href;
123
+ }
124
+
125
+ getVariant(): ButonVariants {
126
+ return this.variant;
127
+ }
128
+
129
+ getColor(): Colors {
130
+ return this.color;
131
+ }
132
+
133
+ getSize(): ButonSizes {
134
+ return this.size;
135
+ }
136
+
137
+ getHref(): string {
138
+ return this.href;
139
+ }
140
+
141
+ getText(): string {
142
+ return this.text;
143
+ }
144
+
145
+ public getRequiredWidth(): number {
146
+ return this.requiredWidth;
147
+ }
148
+ }
149
+
150
+ export type wButtonProps = WidgetProps & {
151
+ text: string;
152
+ variant?: ButonVariants | null;
153
+ color?: Colors | null;
154
+ width?: number | null;
155
+ height?: number | null;
156
+ };
157
+
158
+ export const WButton = (props: wButtonProps) => {
159
+ if (!props.id) {
160
+ props.id = "button." + UID();
161
+ }
162
+
163
+ connectWidgetCallback(props.id, getOnlyEventProps(props));
164
+
165
+ return normalizeWidget(
166
+ <button
167
+ id={props.id}
168
+ w-button
169
+ w-text={props.text}
170
+ w-variant={props.variant}
171
+ w-color={props.color}
172
+ w-width={props.width}
173
+ w-height={props.height}
174
+ />,
175
+ props
176
+ );
177
+ };
178
+
179
+ export function createButton(id: string, content: any, parent: Widget | null = null): Button {
180
+ let newButton = new Button(id, parent);
181
+
182
+ const dataText = content.getAttribute("w-text");
183
+ const dataVariant = content.getAttribute("w-variant");
184
+ const dataColor = content.getAttribute("w-color");
185
+ const dataWidth = content.getAttribute("w-width");
186
+ const dataHeight = content.getAttribute("w-height");
187
+
188
+ if (dataText) {
189
+ newButton.setText(dataText);
190
+ }
191
+
192
+ if (dataVariant) {
193
+ newButton.setVariant(dataVariant);
194
+ }
195
+
196
+ if (dataColor) {
197
+ newButton.setColor(dataColor);
198
+ }
199
+
200
+ if (dataWidth) {
201
+ newButton.setInitialW(dataWidth);
202
+ }
203
+
204
+ if (dataHeight) {
205
+ newButton.setInitialH(dataHeight);
206
+ }
207
+
208
+ return newButton;
209
+ }
@@ -0,0 +1,87 @@
1
+ import "./styles/buttoncolor.css";
2
+ import { Button, wButtonProps } from "./button.ui";
3
+ import { connectWidgetCallback, getOnlyEventProps, Widget } from "./widget.ui";
4
+ import { normalizeWidget } from "./widget.builder";
5
+ import { UID } from "../core/uid";
6
+
7
+ export class ButtonColor extends Button {
8
+ inputColor: Widget;
9
+ constructor(id: string, parent: Widget | null = null) {
10
+ super(id, parent);
11
+
12
+ this.inputColor = new Widget(id + ".inputColor", "input", this);
13
+ this.inputColor.getBody().setAttribute("type", "color");
14
+ this.inputColor.addClass("WUIButtonColorInput");
15
+ }
16
+
17
+ public setValue(value: string): void {
18
+ this.inputColor.getBody().setAttribute("value", value);
19
+ }
20
+
21
+ public getValue(): string {
22
+ const value = this.inputColor.getBody().getAttribute("value");
23
+
24
+ return value ? value : "";
25
+ }
26
+ }
27
+
28
+ export type wButtonColorProps = Omit<wButtonProps, "text"> & {
29
+ value: string;
30
+ };
31
+
32
+ export const WButtonColor = (props: wButtonColorProps) => {
33
+ if (!props.id) {
34
+ props.id = "ButtonColor." + UID();
35
+ }
36
+
37
+ connectWidgetCallback(props.id, getOnlyEventProps(props));
38
+
39
+ return normalizeWidget(
40
+ <button
41
+ id={props.id}
42
+ w-button-color
43
+ w-value={props.value}
44
+ w-variant={props.variant}
45
+ w-color={props.color}
46
+ w-width={props.width}
47
+ w-height={props.height}
48
+ />,
49
+ props
50
+ );
51
+ };
52
+
53
+ export function createButtonColor(
54
+ id: string,
55
+ content: any,
56
+ parent: Widget | null = null
57
+ ): ButtonColor {
58
+ let newButton = new ButtonColor(id, parent);
59
+
60
+ const dataValue = content.getAttribute("w-value");
61
+ const dataVariant = content.getAttribute("w-variant");
62
+ const dataColor = content.getAttribute("w-color");
63
+ const dataWidth = content.getAttribute("w-width");
64
+ const dataHeight = content.getAttribute("w-height");
65
+
66
+ if (dataValue) {
67
+ newButton.setValue(dataValue);
68
+ }
69
+
70
+ if (dataVariant) {
71
+ newButton.setVariant(dataVariant);
72
+ }
73
+
74
+ if (dataColor) {
75
+ newButton.setColor(dataColor);
76
+ }
77
+
78
+ if (dataWidth) {
79
+ newButton.setInitialW(dataWidth);
80
+ }
81
+
82
+ if (dataHeight) {
83
+ newButton.setInitialH(dataHeight);
84
+ }
85
+
86
+ return newButton;
87
+ }
@@ -0,0 +1,134 @@
1
+ import { UID } from "../core/uid";
2
+ import { SelectItem } from "../types/select.item.type";
3
+ import { Button, wButtonProps } from "./button.ui";
4
+ import { Menu } from "./menu.ui";
5
+ import { normalizeWidget, WidgetProps } from "./widget.builder";
6
+ import { Widget } from "./widget.ui";
7
+
8
+ export class ButtonMenu extends Button {
9
+ menu: Menu;
10
+ items: Array<SelectItem>;
11
+ selectedItem: SelectItem | null;
12
+
13
+ public constructor(id: string) {
14
+ super(id);
15
+
16
+ this.menu = new Menu(this.id + ".menu", this.id, null);
17
+
18
+ this.items = new Array<SelectItem>();
19
+ this.selectedItem = null;
20
+
21
+ this.subscribe({
22
+ event: "click",
23
+ then: () => {
24
+ this.menu.clearOptions();
25
+ this.items.forEach((item) => {
26
+ this.menu.addOption(item.id, item.icon, item.label);
27
+ });
28
+
29
+ this.menu.wakeUp();
30
+
31
+ if (this.getW() > this.menu.getW()) {
32
+ this.menu.setW(this.getBody().clientWidth);
33
+ console.log("cambiando ancho...");
34
+ }
35
+ },
36
+ });
37
+
38
+ /*this.menu.subscribe({
39
+ event: "option-clicked",
40
+ then: (_e, clickedOption) => {
41
+ const option = clickedOption as IconButton;
42
+
43
+ const fintOption = this.items.find((item) => item.id === option.id);
44
+
45
+ if (fintOption) {
46
+ this.selectedItem = fintOption;
47
+ }
48
+
49
+ const selectedText = this.selectedItem?.label;
50
+ if (selectedText) {
51
+ this.setText(selectedText);
52
+ } else {
53
+ this.setText("");
54
+ }
55
+ },
56
+ });*/
57
+ }
58
+
59
+ public addItem(id: string, label: string, icon: string): void {
60
+ this.items.push(new SelectItem(id, label, icon));
61
+ }
62
+ }
63
+
64
+ export type WButtonMenuProps = WidgetProps &
65
+ wButtonProps & {
66
+ children: any;
67
+ };
68
+
69
+ export type WButtonMenuItemProps = {
70
+ id: string;
71
+ label?: string | null;
72
+ icon?: string | null;
73
+ };
74
+
75
+ export const WButtonMenu = (props: WButtonMenuProps) => {
76
+ if (!props.id) {
77
+ props.id = "ButtonMenu." + UID();
78
+ }
79
+
80
+ return normalizeWidget(
81
+ <div
82
+ id={props.id}
83
+ w-button-menu
84
+ w-text={props.text}
85
+ w-variant={props.variant}
86
+ w-color={props.color}
87
+ >
88
+ {props.children}
89
+ </div>,
90
+ props
91
+ );
92
+ };
93
+
94
+ export const WButtonMenuItem = (props: WButtonMenuItemProps) => {
95
+ return <div w-button-menu-item id={props.id} w-label={props.label} w-icon={props.icon}></div>;
96
+ };
97
+
98
+ export function createButtonMenu(
99
+ id: string,
100
+ content: any,
101
+ _parent: Widget | null = null
102
+ ): ButtonMenu {
103
+ let newButtonMenu = new ButtonMenu(id);
104
+
105
+ const btnText = content.getAttribute("w-text");
106
+ const btnColor = content.getAttribute("w-color");
107
+ const btnVariant = content.getAttribute("w-variant");
108
+
109
+ if (btnText) {
110
+ newButtonMenu.setText(btnText);
111
+ }
112
+
113
+ if (btnColor) {
114
+ newButtonMenu.setColor(btnColor);
115
+ }
116
+
117
+ if (btnVariant) {
118
+ newButtonMenu.setVariant(btnVariant);
119
+ }
120
+
121
+ content.childNodes.forEach((menuItem: HTMLElement, index: number) => {
122
+ if (menuItem.getAttribute("w-button-menu-item") !== null) {
123
+ const itemId = menuItem.getAttribute("id");
124
+ const itemLabel = menuItem.getAttribute("w-label");
125
+ const itemIcon = menuItem.getAttribute("w-icon");
126
+
127
+ if (itemId !== null) {
128
+ newButtonMenu.addItem(itemId, itemLabel || "Unnamed" + index, itemIcon || "");
129
+ }
130
+ }
131
+ });
132
+
133
+ return newButtonMenu;
134
+ }
@@ -1,12 +1,21 @@
1
1
  import { OrientationTypes } from "src/types/orientation.type";
2
2
  import { IconButton } from "./IconButton.ui";
3
3
  import { ButonVariants, Button } from "./button.ui";
4
- import { Widget, WidgetAlignTypes, WidgetTypes } from "./widget.ui";
4
+ import {
5
+ connectWidgetCallback,
6
+ getOnlyEventProps,
7
+ Widget,
8
+ WidgetAlignTypes,
9
+ WidgetTypes,
10
+ } from "./widget.ui";
11
+ import { createWidget, normalizeWidget, WidgetProps } from "./widget.builder";
12
+ import { UID } from "../core/uid";
5
13
 
6
14
  export class ButtonStack extends Widget {
7
15
  orientation: OrientationTypes;
8
16
  buttons: Map<string, Button | IconButton>;
9
17
  activeButton: string | null;
18
+ centeredButtons: boolean;
10
19
  constructor(
11
20
  id: string,
12
21
  orientation: OrientationTypes = "horizontal",
@@ -14,6 +23,8 @@ export class ButtonStack extends Widget {
14
23
  ) {
15
24
  super(id, "div", parent);
16
25
 
26
+ this.centeredButtons = false;
27
+
17
28
  this.orientation = orientation;
18
29
 
19
30
  if (this.orientation === "horizontal") {
@@ -74,6 +85,9 @@ export class ButtonStack extends Widget {
74
85
 
75
86
  public addButton(button: Button | IconButton): void {
76
87
  this.buttons.set(button.id, button);
88
+ if (button instanceof IconButton && this.centeredButtons) {
89
+ (button as IconButton).setCenterX(true);
90
+ }
77
91
  button.setType(WidgetTypes.FILL);
78
92
  button.subscribe({ event: "click", then: () => this.setActive(button.id) });
79
93
  this.addChild(button);
@@ -91,4 +105,56 @@ export class ButtonStack extends Widget {
91
105
  private thereAreMoreThanTwoButtons(): boolean {
92
106
  return this.buttons.size > 2;
93
107
  }
108
+
109
+ public setCenteredButtons(centeredButtons: boolean): void {
110
+ this.centeredButtons = centeredButtons;
111
+ }
112
+ }
113
+
114
+ export type WButtonStackProps = WidgetProps & {
115
+ centerX?: boolean | null;
116
+ children: any;
117
+ };
118
+
119
+ export const WButtonStack = (props: WButtonStackProps) => {
120
+ if (!props.id) {
121
+ props.id = "ButtonStack." + UID();
122
+ }
123
+
124
+ connectWidgetCallback(props.id, getOnlyEventProps(props));
125
+
126
+ return normalizeWidget(
127
+ <div id={props.id} w-button-stack w-centerX={props.centerX}>
128
+ {props.children}
129
+ </div>,
130
+ props
131
+ );
132
+ };
133
+
134
+ export function createButtonStack(
135
+ id: string,
136
+ content: any,
137
+ parent: Widget | null = null
138
+ ): ButtonStack {
139
+ const dataOrientation = content.getAttribute("w-orientation")
140
+ ? content.getAttribute("w-orientation")
141
+ : "vertical";
142
+
143
+ let newStack = new ButtonStack(id, dataOrientation, parent);
144
+
145
+ if (content.getAttribute("w-centerX")) {
146
+ newStack.setCenteredButtons(true);
147
+ }
148
+
149
+ content.childNodes.forEach((item: HTMLElement, _index: number) => {
150
+ if (item.getAttribute("w-button") || item.getAttribute("w-icon-button")) {
151
+ const widget = createWidget(item) as Button;
152
+
153
+ if (widget !== null) {
154
+ newStack.addButton(widget);
155
+ }
156
+ }
157
+ });
158
+
159
+ return newStack;
94
160
  }