Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recompute css when columns change #612

Merged
merged 5 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no-install commitlint --edit $1
8 changes: 4 additions & 4 deletions lib/settings/use-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useDOMColumns } from '../use-dom-columns';
export default ({ settingsId, host }) => {
const initial = useMemo(
() => Object.fromEntries(sgProps.map((k) => [k, host[k]])),
[]
[],
),
resetRef = useRef(),
onReset = useCallback(() => {
Expand All @@ -19,7 +19,7 @@ export default ({ settingsId, host }) => {
settingsId,
settings,
setSettings,
onReset
onReset,
),
{ enabledColumns } = host,
columns = useDOMColumns(host, { enabledColumns }),
Expand All @@ -31,14 +31,14 @@ export default ({ settingsId, host }) => {
savedSettings,
initial,
}),
[columns, settings, savedSettings]
[columns, settings, savedSettings],
),
normalizedColumns = useMemo(
() =>
normalizedSettings.columns
.map((s) => columns.find((c) => c.name === s.name))
.filter(Boolean),
[columns, ...normalizedSettings.columns.map((s) => s.name)]
[columns, ...normalizedSettings.columns.map((s) => s.name)],
);

return {
Expand Down
315 changes: 162 additions & 153 deletions lib/use-dom-columns.js
Original file line number Diff line number Diff line change
@@ -1,158 +1,167 @@
import { useEffect, useLayoutEffect, useState } from '@pionjs/pion';
import { useLayoutEffect, useState } from '@pionjs/pion';
import { memooize } from '@neovici/cosmoz-utils/memoize';

const columnSymbol = Symbol('column'),
verifyColumnSetup = (columns) => {
let ok = true;
const columnNames = columns.map((c) => c.name);
// Check if column names are set
columns.forEach((column) => {
if (column.name != null) {
return;
}
ok = false;
// eslint-disable-next-line no-console
console.error(
'The name attribute needs to be set on all columns! Missing on column',
column,
);
});

columns.forEach((column) => {
if (
columnNames.indexOf(column.name) ===
columnNames.lastIndexOf(column.name)
) {
return;
}
ok = false;
// eslint-disable-next-line no-console
console.error(
'The name attribute needs to be unique among all columns! Not unique on column',
column,
);
});
return ok;
},
// eslint-disable-next-line max-lines-per-function
domColumnsToConfig = (host, { enabledColumns }) => {
const domColumns = host.shadowRoot
.querySelector('#columnsSlot')
.assignedElements({ flatten: true })
.filter((child) => child.isOmnitableColumn && !child.hidden);

if (!verifyColumnSetup(domColumns)) {
return [];
const columnSymbol = Symbol('column');
const verifyColumnSetup = (columns) => {
let ok = true;
const columnNames = columns.map((c) => c.name);
// Check if column names are set
columns.forEach((column) => {
if (column.name != null) {
return;
}

const columns = Array.isArray(enabledColumns)
? domColumns.filter((column) => enabledColumns.includes(column.name))
: domColumns.filter((column) => !column.disabled);

// eslint-disable-next-line max-lines-per-function
return columns.map((column) => {
const valuePath = column.valuePath ?? column.name;

return {
name: column.name,
title: column.title,

valuePath,
groupOn: column.groupOn ?? valuePath,
sortOn: column.sortOn ?? valuePath,

minWidth: column.minWidth,
width: column.width,
flex: column.flex,
priority: column.priority,

getString: column.getString,
getComparableValue: column.getComparableValue,
serializeFilter: column.serializeFilter,
deserializeFilter: column.deserializeFilter,
toXlsxValue: column.toXlsxValue,

renderHeader: column.renderHeader,
renderCell: column.renderCell,
renderEditCell: column.renderEditCell,
renderGroup: column.renderGroup,
cellTitleFn: column.cellTitleFn,
getFilterFn: column.getFilterFn,
headerCellClass: column.headerCellClass,
cellClass: column.cellClass,

editable: column.editable,

values: column.values,
source: memooize(column.computeSource),

noLocalFilter: column.noLocalFilter,

mini: column.mini,
renderMini: column.renderMini,

// @deprecated
loading: column.loading,
externalValues: column.externalValues,
computeSource: column.computeSource,

// boolean columns
trueLabel: column.trueLabel,
falseLabel: column.falseLabel,

// list columns
valueProperty: column.valueProperty,
textProperty: column.textProperty,
emptyLabel: column.emptyLabel,
emptyValue: column.emptyValue,

// range columns
min: column.min,
max: column.max,
locale: column.locale,
autoupdate: column.autoupdate,

// number columns
maximumFractionDigits: column.maximumFractionDigits,
minimumFractionDigits: column.minimumFractionDigits,

// amount columns
currency: column.currency,
rates: column.rates,
autodetect: column.autodetect,

// treenode columns
ownerTree: column.ownerTree,
keyProperty: column.keyProperty,

...column.getConfig?.(column),

[columnSymbol]: column,
};
});
},
useDOMColumns = (host, { enabledColumns }) => {
const [columns, setColumns] = useState([]);

useLayoutEffect(() => {
setColumns(domColumnsToConfig(host, { enabledColumns }));
}, []);

useEffect(() => {
const slot = host.shadowRoot.querySelector('#columnsSlot'),
handler = () =>
setColumns(domColumnsToConfig(host, { enabledColumns }));

handler();
slot.addEventListener('slotchange', handler);
host.addEventListener('cosmoz-column-prop-changed', handler);
return () => {
slot.removeEventListener('slotchange', handler);
host.removeEventListener('cosmoz-column-prop-changed', handler);
};
}, [enabledColumns]);

return columns;
ok = false;
// eslint-disable-next-line no-console
console.error(
'The name attribute needs to be set on all columns! Missing on column',
column,
);

Check warning on line 18 in lib/use-dom-columns.js

View check run for this annotation

Codecov / codecov/patch

lib/use-dom-columns.js#L13-L18

Added lines #L13 - L18 were not covered by tests
});

columns.forEach((column) => {
if (
columnNames.indexOf(column.name) === columnNames.lastIndexOf(column.name)
) {
return;
}
ok = false;
// eslint-disable-next-line no-console
console.error(
'The name attribute needs to be unique among all columns! Not unique on column',
column,
);

Check warning on line 32 in lib/use-dom-columns.js

View check run for this annotation

Codecov / codecov/patch

lib/use-dom-columns.js#L27-L32

Added lines #L27 - L32 were not covered by tests
});
return ok;
};

// eslint-disable-next-line max-lines-per-function
const normalizeColumn = (column) => {
const valuePath = column.valuePath ?? column.name;

return {
name: column.name,
title: column.title,

valuePath,
groupOn: column.groupOn ?? valuePath,
sortOn: column.sortOn ?? valuePath,

minWidth: column.minWidth,
width: column.width,
flex: column.flex,
priority: column.priority,

getString: column.getString,
getComparableValue: column.getComparableValue,
serializeFilter: column.serializeFilter,
deserializeFilter: column.deserializeFilter,
toXlsxValue: column.toXlsxValue,

renderHeader: column.renderHeader,
renderCell: column.renderCell,
renderEditCell: column.renderEditCell,
renderGroup: column.renderGroup,
cellTitleFn: column.cellTitleFn,
getFilterFn: column.getFilterFn,
headerCellClass: column.headerCellClass,
cellClass: column.cellClass,

editable: column.editable,

values: column.values,
source: memooize(column.computeSource),

noLocalFilter: column.noLocalFilter,

mini: column.mini,
renderMini: column.renderMini,

// @deprecated
loading: column.loading,
externalValues: column.externalValues,
computeSource: column.computeSource,

// boolean columns
trueLabel: column.trueLabel,
falseLabel: column.falseLabel,

// list columns
valueProperty: column.valueProperty,
textProperty: column.textProperty,
emptyLabel: column.emptyLabel,
emptyValue: column.emptyValue,

// range columns
min: column.min,
max: column.max,
locale: column.locale,
autoupdate: column.autoupdate,

// number columns
maximumFractionDigits: column.maximumFractionDigits,
minimumFractionDigits: column.minimumFractionDigits,

// amount columns
currency: column.currency,
rates: column.rates,
autodetect: column.autodetect,

// treenode columns
ownerTree: column.ownerTree,
keyProperty: column.keyProperty,

...column.getConfig?.(column),

[columnSymbol]: column,
};
};

const isVisibleColumn = (child) => child.isOmnitableColumn && !child.hidden;

const collectDomColumns = (slot) => {
const domColumns = slot
.assignedElements({ flatten: true })
.filter(isVisibleColumn);

if (!verifyColumnSetup(domColumns)) return [];
return domColumns;
};

const normalizeColumns = (domColumns, enabledColumns) => {
const columns = Array.isArray(enabledColumns)
? domColumns.filter((column) => enabledColumns.includes(column.name))
: domColumns.filter((column) => !column.disabled);

return columns.map(normalizeColumn);
};

export const useDOMColumns = (host, { enabledColumns }) => {
const [columns, setColumns] = useState([]);

useLayoutEffect(() => {
let sched;
const slot = host.shadowRoot.querySelector('#columnsSlot');
const update = () => {
setColumns(normalizeColumns(collectDomColumns(slot), enabledColumns));
};
const scheduleUpdate = () => {
cancelAnimationFrame(sched);
sched = requestAnimationFrame(update);
};

scheduleUpdate();

slot.addEventListener('slotchange', scheduleUpdate);
host.addEventListener('cosmoz-column-prop-changed', scheduleUpdate);

return () => {
slot.removeEventListener('slotchange', scheduleUpdate);
host.removeEventListener('cosmoz-column-prop-changed', scheduleUpdate);
cancelAnimationFrame(sched);
};
}, [enabledColumns]);

return columns;
};

export { columnSymbol, useDOMColumns };
export { columnSymbol };
2 changes: 1 addition & 1 deletion lib/use-fast-layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const useFastLayout = ({
tweenedlayout = useTweenArray(layout, resizeSpeedFactor),
layoutCss = useMemo(
() => toCss(tweenedlayout, settings.columns),
[tweenedlayout],
[tweenedlayout, settings.columns],
),
collapsedColumns = useMemo(
() =>
Expand Down
Loading