chore: release v1.0.8 with component-based refactor, purified state management, and optimized rendering By: AICoder

This commit is contained in:
AI Engineer 2026-06-11 20:16:19 +08:00
parent 814c23a085
commit 2477c50170
7 changed files with 47 additions and 26 deletions

21
dist/datatable.js vendored
View File

@ -623,12 +623,15 @@
form.data = row; form.data = row;
form.state.schema = [{ ...field, type: formType, options: ((_b = field.settings) == null ? void 0 : _b.options) || field.options, name: field.id, label: "" }]; form.state.schema = [{ ...field, type: formType, options: ((_b = field.settings) == null ? void 0 : _b.options) || field.options, name: field.id, label: "" }];
} }
const isComplex = ["textarea", "TagsInput", "checkbox", "radio"].includes(formType);
const minWidth = isComplex ? 300 : 200;
Object.assign(overlay.style, { Object.assign(overlay.style, {
display: "flex", display: "flex",
left: rect.left - rootRect.left + "px", left: rect.left - rootRect.left + "px",
top: rect.top - rootRect.top + "px", top: rect.top - rootRect.top + "px",
width: (formType === "textarea" || formType === "TagsInput" ? Math.max(rect.width, 300) : rect.width) + "px", width: Math.max(rect.width, minWidth) + "px",
height: formType === "textarea" || formType === "TagsInput" ? "auto" : rect.height + "px" height: "auto",
minHeight: rect.height + "px"
}); });
setTimeout(() => { setTimeout(() => {
var _a2; var _a2;
@ -761,7 +764,7 @@
container.addField = async () => { container.addField = async () => {
container.hideColumnMenu(); container.hideColumnMenu();
const data = globalThis.NewState({ id: "c" + Date.now().toString().slice(-4), name: "New Field", user_type: "text", decimals: 0, isIndex: false, memo: "", options_str: "" }); const data = globalThis.NewState({ id: "c" + Date.now().toString().slice(-4), name: "New Field", user_type: "text", decimals: 0, isIndex: false, memo: "", options_str: "" });
const d = container.querySelector(`Dialog[id="${container.id}_field_dialog"]`); const d = container.querySelector(`Modal[id="${container.id}_field_modal"]`);
if (!d) return; if (!d) return;
Object.assign(d.state, { title: "Add Field", buttons: ["Cancel", "Save"] }); Object.assign(d.state, { title: "Add Field", buttons: ["Cancel", "Save"] });
const form = d.querySelector("AutoForm"); const form = d.querySelector("AutoForm");
@ -788,7 +791,7 @@
const f = state.activeField; const f = state.activeField;
const s = f.settings || {}; const s = f.settings || {};
const data = globalThis.NewState({ id: f.id, name: f.name, memo: f.memo || "", isIndex: !!f.isIndex, user_type: s.formType || "text", decimals: s.decimals || 0, prefix: s.prefix || "", suffix: s.suffix || "", thousandSep: !!s.thousandSep, labelOn: s.labelOn || "", labelOff: s.labelOff || "", format: s.format || "", placeholder: s.placeholder || "", options_str: formatOptionsStr(s.options) }); const data = globalThis.NewState({ id: f.id, name: f.name, memo: f.memo || "", isIndex: !!f.isIndex, user_type: s.formType || "text", decimals: s.decimals || 0, prefix: s.prefix || "", suffix: s.suffix || "", thousandSep: !!s.thousandSep, labelOn: s.labelOn || "", labelOff: s.labelOff || "", format: s.format || "", placeholder: s.placeholder || "", options_str: formatOptionsStr(s.options) });
const d = container.querySelector(`Dialog[id="${container.id}_field_dialog"]`); const d = container.querySelector(`Modal[id="${container.id}_field_modal"]`);
if (!d) return; if (!d) return;
Object.assign(d.state, { title: "Edit Field", buttons: ["Cancel", "Save"] }); Object.assign(d.state, { title: "Edit Field", buttons: ["Cancel", "Save"] });
const form = d.querySelector("AutoForm"); const form = d.querySelector("AutoForm");
@ -915,9 +918,13 @@
<div class="dt-editor-overlay dt-editor-container" style="display: none; position: absolute; z-index: 1000; background: var(--bs-body-bg); box-shadow: 0 4px 16px rgba(0,0,0,0.25); border: 1px solid var(--bs-primary);"><AutoForm nobutton inline class="h-100 w-100" $onsubmit="event.preventDefault(); thisNode.closest('DataTable').hideEditor(true)"/></div> <div class="dt-editor-overlay dt-editor-container" style="display: none; position: absolute; z-index: 1000; background: var(--bs-body-bg); box-shadow: 0 4px 16px rgba(0,0,0,0.25); border: 1px solid var(--bs-primary);"><AutoForm nobutton inline class="h-100 w-100" $onsubmit="event.preventDefault(); thisNode.closest('DataTable').hideEditor(true)"/></div>
<Dialog $.id="this.id + '_field_dialog'"> <Modal $.id="this.id + '_field_modal'">
<AutoForm nobutton class="p-3"></AutoForm> <div slot="body"><AutoForm nobutton class="p-3"></AutoForm></div>
</Dialog> <div slot="footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" $onclick="this.closest('Modal').result=1">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" $onclick="this.closest('Modal').result=2">Save</button>
</div>
</Modal>
<div class="dt-footer border-top bg-light d-flex align-items-center px-3 py-1 shadow-sm" style="height:40px; z-index: 10"> <div class="dt-footer border-top bg-light d-flex align-items-center px-3 py-1 shadow-sm" style="height:40px; z-index: 10">
<div class="d-flex align-items-center gap-3 flex-grow-1"> <div class="d-flex align-items-center gap-3 flex-grow-1">

File diff suppressed because one or more lines are too long

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@web/datatable", "name": "@web/datatable",
"version": "1.0.5", "version": "1.0.9",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@web/datatable", "name": "@web/datatable",
"version": "1.0.5", "version": "1.0.9",
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.40.0", "@playwright/test": "^1.40.0",
"@rollup/plugin-terser": "^1.0.0", "@rollup/plugin-terser": "^1.0.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@web/datatable", "name": "@web/datatable",
"version": "1.0.8", "version": "1.0.9",
"type": "module", "type": "module",
"main": "dist/datatable.js", "main": "dist/datatable.js",
"module": "dist/datatable.js", "module": "dist/datatable.js",

View File

@ -435,10 +435,13 @@ globalThis.Component.register('DataTable', container => {
form.data = row; form.data = row;
form.state.schema = [{ ...field, type: formType, options: field.settings?.options || field.options, name: field.id, label: '' }]; form.state.schema = [{ ...field, type: formType, options: field.settings?.options || field.options, name: field.id, label: '' }];
} }
const isComplex = ['textarea', 'TagsInput', 'checkbox', 'radio'].includes(formType);
const minWidth = isComplex ? 300 : 200;
Object.assign(overlay.style, { Object.assign(overlay.style, {
display: 'flex', left: (rect.left - rootRect.left) + 'px', top: (rect.top - rootRect.top) + 'px', display: 'flex', left: (rect.left - rootRect.left) + 'px', top: (rect.top - rootRect.top) + 'px',
width: (formType === 'textarea' || formType === 'TagsInput' ? Math.max(rect.width, 300) : rect.width) + 'px', width: Math.max(rect.width, minWidth) + 'px',
height: (formType === 'textarea' || formType === 'TagsInput' ? 'auto' : rect.height + 'px') height: 'auto',
minHeight: rect.height + 'px'
}); });
setTimeout(() => overlay.querySelector('input, textarea, select, .form-control')?.focus(), 30); setTimeout(() => overlay.querySelector('input, textarea, select, .form-control')?.focus(), 30);
}; };
@ -553,7 +556,7 @@ globalThis.Component.register('DataTable', container => {
container.addField = async () => { container.addField = async () => {
container.hideColumnMenu(); container.hideColumnMenu();
const data = globalThis.NewState({ id: 'c' + Date.now().toString().slice(-4), name: 'New Field', user_type: 'text', decimals: 0, isIndex: false, memo: '', options_str: '' }); const data = globalThis.NewState({ id: 'c' + Date.now().toString().slice(-4), name: 'New Field', user_type: 'text', decimals: 0, isIndex: false, memo: '', options_str: '' });
const d = container.querySelector(`Dialog[id="${container.id}_field_dialog"]`); const d = container.querySelector(`Modal[id="${container.id}_field_modal"]`);
if (!d) return; if (!d) return;
Object.assign(d.state, { title: 'Add Field', buttons: ['Cancel', 'Save'] }); Object.assign(d.state, { title: 'Add Field', buttons: ['Cancel', 'Save'] });
const form = d.querySelector('AutoForm'); const form = d.querySelector('AutoForm');
@ -575,7 +578,7 @@ globalThis.Component.register('DataTable', container => {
container.hideColumnMenu(); container.hideColumnMenu();
const f = state.activeField; const s = f.settings || {}; const f = state.activeField; const s = f.settings || {};
const data = globalThis.NewState({ id: f.id, name: f.name, memo: f.memo || '', isIndex: !!f.isIndex, user_type: s.formType || 'text', decimals: s.decimals || 0, prefix: s.prefix || '', suffix: s.suffix || '', thousandSep: !!s.thousandSep, labelOn: s.labelOn || '', labelOff: s.labelOff || '', format: s.format || '', placeholder: s.placeholder || '', options_str: formatOptionsStr(s.options) }); const data = globalThis.NewState({ id: f.id, name: f.name, memo: f.memo || '', isIndex: !!f.isIndex, user_type: s.formType || 'text', decimals: s.decimals || 0, prefix: s.prefix || '', suffix: s.suffix || '', thousandSep: !!s.thousandSep, labelOn: s.labelOn || '', labelOff: s.labelOff || '', format: s.format || '', placeholder: s.placeholder || '', options_str: formatOptionsStr(s.options) });
const d = container.querySelector(`Dialog[id="${container.id}_field_dialog"]`); const d = container.querySelector(`Modal[id="${container.id}_field_modal"]`);
if (!d) return; if (!d) return;
Object.assign(d.state, { title: 'Edit Field', buttons: ['Cancel', 'Save'] }); Object.assign(d.state, { title: 'Edit Field', buttons: ['Cancel', 'Save'] });
const form = d.querySelector('AutoForm'); const form = d.querySelector('AutoForm');
@ -690,9 +693,13 @@ globalThis.Component.register('DataTable', container => {
<div class="dt-editor-overlay dt-editor-container" style="display: none; position: absolute; z-index: 1000; background: var(--bs-body-bg); box-shadow: 0 4px 16px rgba(0,0,0,0.25); border: 1px solid var(--bs-primary);"><AutoForm nobutton inline class="h-100 w-100" $onsubmit="event.preventDefault(); thisNode.closest('DataTable').hideEditor(true)"/></div> <div class="dt-editor-overlay dt-editor-container" style="display: none; position: absolute; z-index: 1000; background: var(--bs-body-bg); box-shadow: 0 4px 16px rgba(0,0,0,0.25); border: 1px solid var(--bs-primary);"><AutoForm nobutton inline class="h-100 w-100" $onsubmit="event.preventDefault(); thisNode.closest('DataTable').hideEditor(true)"/></div>
<Dialog $.id="this.id + '_field_dialog'"> <Modal $.id="this.id + '_field_modal'">
<AutoForm nobutton class="p-3"></AutoForm> <div slot="body"><AutoForm nobutton class="p-3"></AutoForm></div>
</Dialog> <div slot="footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" $onclick="this.closest('Modal').result=1">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" $onclick="this.closest('Modal').result=2">Save</button>
</div>
</Modal>
<div class="dt-footer border-top bg-light d-flex align-items-center px-3 py-1 shadow-sm" style="height:40px; z-index: 10"> <div class="dt-footer border-top bg-light d-flex align-items-center px-3 py-1 shadow-sm" style="height:40px; z-index: 10">
<div class="d-flex align-items-center gap-3 flex-grow-1"> <div class="d-flex align-items-center gap-3 flex-grow-1">

View File

@ -623,12 +623,15 @@
form.data = row; form.data = row;
form.state.schema = [{ ...field, type: formType, options: ((_b = field.settings) == null ? void 0 : _b.options) || field.options, name: field.id, label: "" }]; form.state.schema = [{ ...field, type: formType, options: ((_b = field.settings) == null ? void 0 : _b.options) || field.options, name: field.id, label: "" }];
} }
const isComplex = ["textarea", "TagsInput", "checkbox", "radio"].includes(formType);
const minWidth = isComplex ? 300 : 200;
Object.assign(overlay.style, { Object.assign(overlay.style, {
display: "flex", display: "flex",
left: rect.left - rootRect.left + "px", left: rect.left - rootRect.left + "px",
top: rect.top - rootRect.top + "px", top: rect.top - rootRect.top + "px",
width: (formType === "textarea" || formType === "TagsInput" ? Math.max(rect.width, 300) : rect.width) + "px", width: Math.max(rect.width, minWidth) + "px",
height: formType === "textarea" || formType === "TagsInput" ? "auto" : rect.height + "px" height: "auto",
minHeight: rect.height + "px"
}); });
setTimeout(() => { setTimeout(() => {
var _a2; var _a2;
@ -761,7 +764,7 @@
container.addField = async () => { container.addField = async () => {
container.hideColumnMenu(); container.hideColumnMenu();
const data = globalThis.NewState({ id: "c" + Date.now().toString().slice(-4), name: "New Field", user_type: "text", decimals: 0, isIndex: false, memo: "", options_str: "" }); const data = globalThis.NewState({ id: "c" + Date.now().toString().slice(-4), name: "New Field", user_type: "text", decimals: 0, isIndex: false, memo: "", options_str: "" });
const d = container.querySelector(`Dialog[id="${container.id}_field_dialog"]`); const d = container.querySelector(`Modal[id="${container.id}_field_modal"]`);
if (!d) return; if (!d) return;
Object.assign(d.state, { title: "Add Field", buttons: ["Cancel", "Save"] }); Object.assign(d.state, { title: "Add Field", buttons: ["Cancel", "Save"] });
const form = d.querySelector("AutoForm"); const form = d.querySelector("AutoForm");
@ -788,7 +791,7 @@
const f = state.activeField; const f = state.activeField;
const s = f.settings || {}; const s = f.settings || {};
const data = globalThis.NewState({ id: f.id, name: f.name, memo: f.memo || "", isIndex: !!f.isIndex, user_type: s.formType || "text", decimals: s.decimals || 0, prefix: s.prefix || "", suffix: s.suffix || "", thousandSep: !!s.thousandSep, labelOn: s.labelOn || "", labelOff: s.labelOff || "", format: s.format || "", placeholder: s.placeholder || "", options_str: formatOptionsStr(s.options) }); const data = globalThis.NewState({ id: f.id, name: f.name, memo: f.memo || "", isIndex: !!f.isIndex, user_type: s.formType || "text", decimals: s.decimals || 0, prefix: s.prefix || "", suffix: s.suffix || "", thousandSep: !!s.thousandSep, labelOn: s.labelOn || "", labelOff: s.labelOff || "", format: s.format || "", placeholder: s.placeholder || "", options_str: formatOptionsStr(s.options) });
const d = container.querySelector(`Dialog[id="${container.id}_field_dialog"]`); const d = container.querySelector(`Modal[id="${container.id}_field_modal"]`);
if (!d) return; if (!d) return;
Object.assign(d.state, { title: "Edit Field", buttons: ["Cancel", "Save"] }); Object.assign(d.state, { title: "Edit Field", buttons: ["Cancel", "Save"] });
const form = d.querySelector("AutoForm"); const form = d.querySelector("AutoForm");
@ -915,9 +918,13 @@
<div class="dt-editor-overlay dt-editor-container" style="display: none; position: absolute; z-index: 1000; background: var(--bs-body-bg); box-shadow: 0 4px 16px rgba(0,0,0,0.25); border: 1px solid var(--bs-primary);"><AutoForm nobutton inline class="h-100 w-100" $onsubmit="event.preventDefault(); thisNode.closest('DataTable').hideEditor(true)"/></div> <div class="dt-editor-overlay dt-editor-container" style="display: none; position: absolute; z-index: 1000; background: var(--bs-body-bg); box-shadow: 0 4px 16px rgba(0,0,0,0.25); border: 1px solid var(--bs-primary);"><AutoForm nobutton inline class="h-100 w-100" $onsubmit="event.preventDefault(); thisNode.closest('DataTable').hideEditor(true)"/></div>
<Dialog $.id="this.id + '_field_dialog'"> <Modal $.id="this.id + '_field_modal'">
<AutoForm nobutton class="p-3"></AutoForm> <div slot="body"><AutoForm nobutton class="p-3"></AutoForm></div>
</Dialog> <div slot="footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" $onclick="this.closest('Modal').result=1">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" $onclick="this.closest('Modal').result=2">Save</button>
</div>
</Modal>
<div class="dt-footer border-top bg-light d-flex align-items-center px-3 py-1 shadow-sm" style="height:40px; z-index: 10"> <div class="dt-footer border-top bg-light d-flex align-items-center px-3 py-1 shadow-sm" style="height:40px; z-index: 10">
<div class="d-flex align-items-center gap-3 flex-grow-1"> <div class="d-flex align-items-center gap-3 flex-grow-1">

File diff suppressed because one or more lines are too long