@rettangoli/ui 0.1.4 → 0.1.5
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/dist/rettangoli-iife-ui.min.js +27 -27
- package/package.json +4 -4
- package/src/components/dropdownMenu/dropdownMenu.handlers.js +2 -2
- package/src/components/dropdownMenu/dropdownMenu.view.yaml +10 -10
- package/src/components/globalUi/globalUi.handlers.js +78 -2
- package/src/components/globalUi/globalUi.store.js +38 -2
- package/src/components/globalUi/globalUi.view.yaml +31 -11
- package/src/deps/createGlobalUI.js +77 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rettangoli/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A UI component library for building web interfaces.",
|
|
5
5
|
"main": "dist/rettangoli-esm.min.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build:dev": "rtgl fe build && bun run esbuild-dev.js",
|
|
26
|
+
"build:dev": "rtgl fe build -d && bun run esbuild-dev.js",
|
|
27
27
|
"build": "rtgl fe build && bun run esbuild.js",
|
|
28
|
-
"vt:generate": "rtgl fe build && bun run esbuild-dev.js && rtgl vt generate --skip-screenshots",
|
|
29
|
-
"vt:report": "bun run build:dev && rtgl vt generate && rtgl vt report",
|
|
28
|
+
"vt:generate": "rtgl fe build -d && bun run esbuild-dev.js && rtgl vt generate --skip-screenshots",
|
|
29
|
+
"vt:report": "bun run build:dev && rtgl vt generate --screenshot-wait-time 500 && rtgl vt report",
|
|
30
30
|
"vt:accept": "rtgl vt accept",
|
|
31
31
|
"serve": "bunx serve .rettangoli/vt/_site"
|
|
32
32
|
},
|
|
@@ -5,10 +5,10 @@ export const handleClosePopover = (deps, payload) => {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export const handleClickMenuItem = (deps, payload) => {
|
|
8
|
-
const { dispatchEvent } = deps;
|
|
8
|
+
const { dispatchEvent, props } = deps;
|
|
9
9
|
const event = payload._event;
|
|
10
10
|
const index = parseInt(event.currentTarget.id.replace('option-', ''));
|
|
11
|
-
const item =
|
|
11
|
+
const item = props.items[index];
|
|
12
12
|
|
|
13
13
|
dispatchEvent(new CustomEvent('click-item', {
|
|
14
14
|
detail: {
|
|
@@ -44,13 +44,13 @@ refs:
|
|
|
44
44
|
|
|
45
45
|
template:
|
|
46
46
|
- rtgl-popover#popover ?open=${open} x=${x} y=${y} placement=${placement}:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
- rtgl-view wh=300 sv g=xs slot=content bgc=background br=md:
|
|
48
|
+
- $for item, i in items:
|
|
49
|
+
- $if item.type == 'label':
|
|
50
|
+
- rtgl-view w=f ph=lg pv=md:
|
|
51
|
+
- rtgl-text s=sm c=mu-fg: ${item.label}
|
|
52
|
+
$elif item.type == 'item':
|
|
53
|
+
- rtgl-view#option-${i} w=f h-bgc=ac ph=lg pv=md cur=p br=md bgc=mu:
|
|
54
|
+
- rtgl-text: ${item.label}
|
|
55
|
+
$elif item.type == 'separator':
|
|
56
|
+
- rtgl-view w=f h=1 ph=lg mv=md bgc=bo:
|
|
@@ -21,12 +21,48 @@ export const handleCancel = (deps, payload) => {
|
|
|
21
21
|
globalUI.emit('event', false);
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
export const handleDropdownClose = (deps, payload) => {
|
|
25
|
+
const { store, render, globalUI } = deps;
|
|
26
|
+
|
|
27
|
+
// Always process close events - the framework will handle if it's already closed
|
|
28
|
+
store.closeDialog();
|
|
29
|
+
render();
|
|
30
|
+
globalUI.emit('event', null);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const handleDropdownItemClick = (deps, payload) => {
|
|
34
|
+
const { store, render, globalUI } = deps;
|
|
35
|
+
const event = payload._event;
|
|
36
|
+
const { index, item } = event.detail;
|
|
37
|
+
|
|
38
|
+
// Always process click events - the framework will handle if it's already closed
|
|
39
|
+
store.closeDialog();
|
|
40
|
+
render();
|
|
41
|
+
globalUI.emit('event', { index, item });
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Shows an alert dialog with the specified options.
|
|
46
|
+
* Closes any existing dialog or dropdown before showing the alert.
|
|
47
|
+
*
|
|
48
|
+
* @param {Object} deps - Dependencies object
|
|
49
|
+
* @param {Object} deps.store - The globalUI store instance
|
|
50
|
+
* @param {Function} deps.render - Function to trigger re-rendering
|
|
51
|
+
* @param {Object} payload - Alert configuration options
|
|
52
|
+
* @param {string} payload.message - The alert message (required)
|
|
53
|
+
* @param {string} [payload.title] - Optional alert title
|
|
54
|
+
* @param {('info'|'warning'|'error')} [payload.status] - Optional status type
|
|
55
|
+
* @param {string} [payload.confirmText] - Text for the confirm button (default: "OK")
|
|
56
|
+
* @returns {void}
|
|
57
|
+
*/
|
|
24
58
|
export const showAlert = (deps, payload) => {
|
|
25
59
|
const { store, render } = deps;
|
|
26
60
|
const options = payload;
|
|
27
61
|
|
|
62
|
+
// Close any existing dialog/dropdown menu first
|
|
28
63
|
if (store.selectIsOpen()) {
|
|
29
|
-
|
|
64
|
+
store.closeDialog();
|
|
65
|
+
render();
|
|
30
66
|
}
|
|
31
67
|
|
|
32
68
|
store.setAlertConfig(options);
|
|
@@ -37,8 +73,10 @@ export const showConfirm = async (deps, payload) => {
|
|
|
37
73
|
const { store, render, globalUI } = deps;
|
|
38
74
|
const options = payload;
|
|
39
75
|
|
|
76
|
+
// Close any existing dialog/dropdown menu first
|
|
40
77
|
if (store.selectIsOpen()) {
|
|
41
|
-
|
|
78
|
+
store.closeDialog();
|
|
79
|
+
render();
|
|
42
80
|
}
|
|
43
81
|
|
|
44
82
|
store.setConfirmConfig(options);
|
|
@@ -50,4 +88,42 @@ export const showConfirm = async (deps, payload) => {
|
|
|
50
88
|
resolve(result)
|
|
51
89
|
});
|
|
52
90
|
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Shows a dropdown menu at the specified position with the given items.
|
|
95
|
+
* Closes any existing dialog or dropdown menu before showing the dropdown menu.
|
|
96
|
+
*
|
|
97
|
+
* @param {Object} deps - Dependencies object
|
|
98
|
+
* @param {Object} deps.store - The globalUI store instance
|
|
99
|
+
* @param {Function} deps.render - Function to trigger re-rendering
|
|
100
|
+
* @param {Object} deps.globalUI - The globalUI event emitter
|
|
101
|
+
* @param {Object} payload - Dropdown menu configuration options
|
|
102
|
+
* @param {Array<Object>} payload.items - Array of dropdown menu items (required)
|
|
103
|
+
* @param {number} payload.x - X coordinate position (required)
|
|
104
|
+
* @param {number} payload.y - Y coordinate position (required)
|
|
105
|
+
* @param {string} [payload.placement] - Dropdown menu placement (default: "bottom-start")
|
|
106
|
+
* @returns {Promise<Object|null>} Promise that resolves with clicked item info or null if closed without selection
|
|
107
|
+
* @returns {Object} [result.index] - Index of the clicked item
|
|
108
|
+
* @returns {Object} [result.item] - The clicked item object
|
|
109
|
+
*/
|
|
110
|
+
export const showDropdownMenu = async (deps, payload) => {
|
|
111
|
+
const { store, render, globalUI } = deps;
|
|
112
|
+
const options = payload;
|
|
113
|
+
|
|
114
|
+
// Close any existing dialog/dropdown menu first
|
|
115
|
+
if (store.selectIsOpen()) {
|
|
116
|
+
store.closeDialog();
|
|
117
|
+
render();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
store.setDropdownConfig(options);
|
|
121
|
+
render();
|
|
122
|
+
|
|
123
|
+
return new Promise((resolve) => {
|
|
124
|
+
globalUI.once('event', (result) => {
|
|
125
|
+
// result contains info of clicked item or null if closed without selection
|
|
126
|
+
resolve(result)
|
|
127
|
+
});
|
|
128
|
+
});
|
|
53
129
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const createInitialState = () => Object.freeze({
|
|
2
2
|
isOpen: false,
|
|
3
|
+
uiType: "dialog", // "dialog" | "dropdown"
|
|
3
4
|
config: {
|
|
4
5
|
status: undefined, // undefined | info | warning | error
|
|
5
6
|
title: "",
|
|
@@ -8,13 +9,19 @@ export const createInitialState = () => Object.freeze({
|
|
|
8
9
|
cancelText: "Cancel",
|
|
9
10
|
mode: "alert", // alert | confirm
|
|
10
11
|
},
|
|
12
|
+
dropdownConfig: {
|
|
13
|
+
items: [],
|
|
14
|
+
x: 0,
|
|
15
|
+
y: 0,
|
|
16
|
+
placement: "bottom-start",
|
|
17
|
+
},
|
|
11
18
|
});
|
|
12
19
|
|
|
13
20
|
export const setAlertConfig = (state, options) => {
|
|
14
21
|
if (!options.message) {
|
|
15
22
|
throw new Error("message is required for showAlert");
|
|
16
23
|
}
|
|
17
|
-
|
|
24
|
+
|
|
18
25
|
state.config = {
|
|
19
26
|
status: options.status || undefined,
|
|
20
27
|
title: options.title || "",
|
|
@@ -23,6 +30,7 @@ export const setAlertConfig = (state, options) => {
|
|
|
23
30
|
cancelText: "",
|
|
24
31
|
mode: "alert",
|
|
25
32
|
};
|
|
33
|
+
state.uiType = "dialog";
|
|
26
34
|
state.isOpen = true;
|
|
27
35
|
};
|
|
28
36
|
|
|
@@ -30,7 +38,7 @@ export const setConfirmConfig = (state, options) => {
|
|
|
30
38
|
if (!options.message) {
|
|
31
39
|
throw new Error("message is required for showConfirm");
|
|
32
40
|
}
|
|
33
|
-
|
|
41
|
+
|
|
34
42
|
state.config = {
|
|
35
43
|
status: options.status || undefined,
|
|
36
44
|
title: options.title || "",
|
|
@@ -39,19 +47,47 @@ export const setConfirmConfig = (state, options) => {
|
|
|
39
47
|
cancelText: options.cancelText || "Cancel",
|
|
40
48
|
mode: "confirm",
|
|
41
49
|
};
|
|
50
|
+
state.uiType = "dialog";
|
|
51
|
+
state.isOpen = true;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const setDropdownConfig = (state, options) => {
|
|
55
|
+
if (!options.items || !Array.isArray(options.items)) {
|
|
56
|
+
throw new Error("items array is required for showDropdown");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
state.dropdownConfig = {
|
|
60
|
+
items: options.items,
|
|
61
|
+
x: options.x || 0,
|
|
62
|
+
y: options.y || 0,
|
|
63
|
+
placement: options.placement || "bottom-start",
|
|
64
|
+
};
|
|
65
|
+
state.uiType = "dropdown";
|
|
42
66
|
state.isOpen = true;
|
|
43
67
|
};
|
|
44
68
|
|
|
45
69
|
export const closeDialog = (state) => {
|
|
46
70
|
state.isOpen = false;
|
|
71
|
+
state.uiType = "dialog"; // Reset to default type
|
|
47
72
|
};
|
|
48
73
|
|
|
49
74
|
export const selectConfig = ({ state }) => state.config;
|
|
75
|
+
export const selectDropdownConfig = ({ state }) => state.dropdownConfig;
|
|
76
|
+
export const selectUiType = ({ state }) => state.uiType;
|
|
50
77
|
export const selectIsOpen = ({ state }) => state.isOpen;
|
|
51
78
|
|
|
52
79
|
export const selectViewData = ({ state }) => {
|
|
53
80
|
return {
|
|
54
81
|
isOpen: state.isOpen,
|
|
82
|
+
uiType: state.uiType,
|
|
55
83
|
config: state.config,
|
|
84
|
+
dropdownConfig: {
|
|
85
|
+
items: state.dropdownConfig?.items || [],
|
|
86
|
+
x: state.dropdownConfig?.x || 0,
|
|
87
|
+
y: state.dropdownConfig?.y || 0,
|
|
88
|
+
placement: state.dropdownConfig?.placement || 'bottom-start',
|
|
89
|
+
},
|
|
90
|
+
isDialogOpen: state.isOpen && state.uiType === 'dialog',
|
|
91
|
+
isDropdownOpen: state.isOpen && state.uiType === 'dropdown',
|
|
56
92
|
};
|
|
57
93
|
};
|
|
@@ -5,6 +5,8 @@ viewDataSchema:
|
|
|
5
5
|
properties:
|
|
6
6
|
isOpen:
|
|
7
7
|
type: boolean
|
|
8
|
+
uiType:
|
|
9
|
+
type: string
|
|
8
10
|
config:
|
|
9
11
|
type: object
|
|
10
12
|
properties:
|
|
@@ -20,6 +22,17 @@ viewDataSchema:
|
|
|
20
22
|
type: string
|
|
21
23
|
mode:
|
|
22
24
|
type: string
|
|
25
|
+
dropdownConfig:
|
|
26
|
+
type: object
|
|
27
|
+
properties:
|
|
28
|
+
items:
|
|
29
|
+
type: array
|
|
30
|
+
x:
|
|
31
|
+
type: number
|
|
32
|
+
y:
|
|
33
|
+
type: number
|
|
34
|
+
placement:
|
|
35
|
+
type: string
|
|
23
36
|
|
|
24
37
|
refs:
|
|
25
38
|
dialog:
|
|
@@ -34,17 +47,24 @@ refs:
|
|
|
34
47
|
eventListeners:
|
|
35
48
|
click:
|
|
36
49
|
handler: handleCancel
|
|
50
|
+
dropdown-menu:
|
|
51
|
+
eventListeners:
|
|
52
|
+
close:
|
|
53
|
+
handler: handleDropdownClose
|
|
54
|
+
click-item:
|
|
55
|
+
handler: handleDropdownItemClick
|
|
37
56
|
|
|
38
57
|
template:
|
|
39
|
-
- rtgl-dialog#dialog ?open=${
|
|
58
|
+
- rtgl-dialog#dialog ?open=${isDialogOpen} s=sm:
|
|
40
59
|
- rtgl-view slot=content g=lg p=lg:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
- rtgl-view d=h g=md:
|
|
61
|
+
- rtgl-view d=h ah=c av=c g=md:
|
|
62
|
+
- rtgl-view g=md:
|
|
63
|
+
- rtgl-view h=24 av=c:
|
|
64
|
+
- rtgl-text fw=600: ${config.title}
|
|
65
|
+
- rtgl-text: ${config.message}
|
|
66
|
+
- rtgl-view d=h g=md mt=lg w=f ah=e:
|
|
67
|
+
- $if config.mode == 'confirm':
|
|
68
|
+
- rtgl-button#cancel-button v=se: ${config.cancelText}
|
|
69
|
+
- rtgl-button#confirm-button v=pr: ${config.confirmText}
|
|
70
|
+
- rtgl-dropdown-menu#dropdown-menu ?open=${isDropdownOpen} x=${dropdownConfig.x} y=${dropdownConfig.y} placement=${dropdownConfig.placement} .items=dropdownConfig.items key=dropdown-${isDropdownOpen}:
|
|
@@ -1,7 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a GlobalUI manager instance for controlling global UI components.
|
|
3
|
+
* Provides methods for showing alerts, confirm dialogs, and dropdown menus.
|
|
4
|
+
*
|
|
5
|
+
* @param {HTMLElement} globalUIElement - The globalUI component element
|
|
6
|
+
* @returns {Object} GlobalUI manager instance
|
|
7
|
+
* @returns {Function} returns.once - Register a one-time event listener
|
|
8
|
+
* @returns {Function} returns.emit - Emit an event to registered listeners
|
|
9
|
+
* @returns {Function} returns.showAlert - Show an alert dialog
|
|
10
|
+
* @returns {Function} returns.showConfirm - Show a confirmation dialog
|
|
11
|
+
* @returns {Function} returns.showDropdownMenu - Show a dropdown menu
|
|
12
|
+
*/
|
|
1
13
|
const createGlobalUI = (globalUIElement) => {
|
|
2
14
|
let listeners = {};
|
|
3
15
|
|
|
4
16
|
return {
|
|
17
|
+
/**
|
|
18
|
+
* Registers a one-time event listener for the specified event.
|
|
19
|
+
* The listener will be automatically removed after the first event.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} event - The event name to listen for
|
|
22
|
+
* @param {Function} callback - The callback function to execute
|
|
23
|
+
* @returns {void}
|
|
24
|
+
*/
|
|
5
25
|
once: (event, callback) => {
|
|
6
26
|
if (!listeners[event]) {
|
|
7
27
|
listeners[event] = [];
|
|
@@ -12,6 +32,14 @@ const createGlobalUI = (globalUIElement) => {
|
|
|
12
32
|
}
|
|
13
33
|
listeners[event].push(onceCallback);
|
|
14
34
|
},
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Emits an event to all registered listeners for the specified event type.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} event - The event name to emit
|
|
40
|
+
* @param {...any} args - Arguments to pass to the event listeners
|
|
41
|
+
* @returns {void}
|
|
42
|
+
*/
|
|
15
43
|
emit: (event, ...args) => {
|
|
16
44
|
if (listeners[event]) {
|
|
17
45
|
listeners[event].forEach(callback => {
|
|
@@ -19,6 +47,19 @@ const createGlobalUI = (globalUIElement) => {
|
|
|
19
47
|
});
|
|
20
48
|
}
|
|
21
49
|
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Shows an alert dialog with the specified options.
|
|
53
|
+
* The alert displays a message with a single OK button.
|
|
54
|
+
*
|
|
55
|
+
* @param {Object} options - Alert configuration options
|
|
56
|
+
* @param {string} options.message - The alert message (required)
|
|
57
|
+
* @param {string} [options.title] - Optional alert title
|
|
58
|
+
* @param {('info'|'warning'|'error')} [options.status] - Optional status type
|
|
59
|
+
* @param {string} [options.confirmText] - Text for the confirm button (default: "OK")
|
|
60
|
+
* @returns {Promise<void>} Promise that resolves when the alert is closed
|
|
61
|
+
* @throws {Error} If globalUIElement is not initialized
|
|
62
|
+
*/
|
|
22
63
|
showAlert: async (options) => {
|
|
23
64
|
if(!globalUIElement)
|
|
24
65
|
{
|
|
@@ -26,12 +67,48 @@ const createGlobalUI = (globalUIElement) => {
|
|
|
26
67
|
}
|
|
27
68
|
globalUIElement.transformedHandlers.showAlert(options);
|
|
28
69
|
},
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Shows a confirmation dialog with the specified options.
|
|
73
|
+
* The dialog displays a message with confirm and cancel buttons.
|
|
74
|
+
*
|
|
75
|
+
* @param {Object} options - Confirmation dialog configuration options
|
|
76
|
+
* @param {string} options.message - The confirmation message (required)
|
|
77
|
+
* @param {string} [options.title] - Optional dialog title
|
|
78
|
+
* @param {('info'|'warning'|'error')} [options.status] - Optional status type
|
|
79
|
+
* @param {string} [options.confirmText] - Text for the confirm button (default: "Yes")
|
|
80
|
+
* @param {string} [options.cancelText] - Text for the cancel button (default: "Cancel")
|
|
81
|
+
* @returns {Promise<boolean>} Promise that resolves to true if confirmed, false if cancelled
|
|
82
|
+
* @throws {Error} If globalUIElement is not initialized
|
|
83
|
+
*/
|
|
29
84
|
showConfirm: async (options) => {
|
|
30
85
|
if(!globalUIElement)
|
|
31
86
|
{
|
|
32
87
|
throw new Error("globalUIElement is not set. Make sure to initialize the global UI component and pass it to createGlobalUIManager.");
|
|
33
88
|
}
|
|
34
89
|
return globalUIElement.transformedHandlers.showConfirm(options);
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Shows a dropdown menu at the specified position with the given items.
|
|
94
|
+
* The dropdown can contain various item types including labels, items, and separators.
|
|
95
|
+
*
|
|
96
|
+
* @param {Object} options - Dropdown menu configuration options
|
|
97
|
+
* @param {Array<Object>} options.items - Array of dropdown menu items (required)
|
|
98
|
+
* @param {number} options.x - X coordinate position (required)
|
|
99
|
+
* @param {number} options.y - Y coordinate position (required)
|
|
100
|
+
* @param {string} [options.placement] - Dropdown menu placement (default: "bottom-start")
|
|
101
|
+
* @returns {Promise<Object|null>} Promise that resolves with clicked item info or null if closed without selection
|
|
102
|
+
* @returns {Object} [result.index] - Index of the clicked item
|
|
103
|
+
* @returns {Object} [result.item] - The clicked item object
|
|
104
|
+
* @throws {Error} If globalUIElement is not initialized
|
|
105
|
+
*/
|
|
106
|
+
showDropdownMenu: async (options) => {
|
|
107
|
+
if(!globalUIElement)
|
|
108
|
+
{
|
|
109
|
+
throw new Error("globalUIElement is not set. Make sure to initialize the global UI component and pass it to createGlobalUIManager.");
|
|
110
|
+
}
|
|
111
|
+
return globalUIElement.transformedHandlers.showDropdownMenu(options);
|
|
35
112
|
}
|
|
36
113
|
};
|
|
37
114
|
}
|