@helpwave/hightide
Version:
helpwave's component and theming library
413 lines (401 loc) • 18.2 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/components/Table.tsx
var Table_exports = {};
__export(Table_exports, {
Table: () => Table,
addElementToTable: () => addElementToTable,
changeTableSelectionSingle: () => changeTableSelectionSingle,
defaultTableStatePagination: () => defaultTableStatePagination,
defaultTableStateSelection: () => defaultTableStateSelection,
isDataObjectSelected: () => isDataObjectSelected,
pageForItem: () => pageForItem,
removeFromTableSelection: () => removeFromTableSelection,
updatePagination: () => updatePagination
});
module.exports = __toCommonJS(Table_exports);
var import_react_custom_scrollbars_2 = require("react-custom-scrollbars-2");
var import_react4 = require("react");
// src/util/noop.ts
var noop = () => void 0;
// src/components/user-input/Checkbox.tsx
var import_react = require("react");
var CheckboxPrimitive = __toESM(require("@radix-ui/react-checkbox"));
var import_lucide_react = require("lucide-react");
var import_clsx = __toESM(require("clsx"));
// src/components/user-input/Label.tsx
var import_jsx_runtime = require("react/jsx-runtime");
var styleMapping = {
labelSmall: "textstyle-label-sm",
labelMedium: "textstyle-label-md",
labelBig: "textstyle-label-lg"
};
var Label = ({
children,
name,
labelType = "labelSmall",
...props
}) => {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { ...props, children: children ? children : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styleMapping[labelType], children: name }) });
};
// src/components/user-input/Checkbox.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var checkboxSizeMapping = {
small: "size-4",
medium: "size-6",
large: "size-8"
};
var checkboxIconSizeMapping = {
small: "size-3",
medium: "size-5",
large: "size-7"
};
var ControlledCheckbox = ({
id,
label,
checked,
disabled,
onChange,
onChangeTristate,
size = "medium",
className = "",
containerClassName
}) => {
const usedSizeClass = checkboxSizeMapping[size];
const innerIconSize = checkboxIconSizeMapping[size];
const propagateChange = (checked2) => {
if (onChangeTristate) {
onChangeTristate(checked2);
}
if (onChange) {
onChange(checked2 === "indeterminate" ? false : checked2);
}
};
const changeValue = () => {
const newValue = checked === "indeterminate" ? false : !checked;
propagateChange(newValue);
};
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: (0, import_clsx.default)("row justify-center items-center", containerClassName), children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
CheckboxPrimitive.Root,
{
onCheckedChange: propagateChange,
checked,
disabled,
id,
className: (0, import_clsx.default)(usedSizeClass, `items-center border-2 rounded outline-none focus:border-primary`, {
"text-disabled-text border-disabled-text": disabled,
"border-on-background": !disabled,
"bg-primary/30 border-primary text-primary": checked === true || checked === "indeterminate",
"hover:border-gray-400 focus:hover:border-primary": !checked
}, className),
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(CheckboxPrimitive.Indicator, { children: [
checked === true && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Check, { className: innerIconSize }),
checked === "indeterminate" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Minus, { className: innerIconSize })
] })
}
),
label && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { ...label, className: (0, import_clsx.default)("cursor-pointer", label.className), htmlFor: id, onClick: changeValue })
] });
};
// src/components/Pagination.tsx
var import_lucide_react2 = require("lucide-react");
var import_clsx2 = __toESM(require("clsx"));
// src/hooks/useLanguage.tsx
var import_react3 = require("react");
// src/hooks/useLocalStorage.tsx
var import_react2 = require("react");
// src/hooks/useLanguage.tsx
var import_jsx_runtime3 = require("react/jsx-runtime");
var DEFAULT_LANGUAGE = "en";
var LanguageContext = (0, import_react3.createContext)({ language: DEFAULT_LANGUAGE, setLanguage: (v) => v });
var useLanguage = () => (0, import_react3.useContext)(LanguageContext);
// src/hooks/useTranslation.ts
var useTranslation = (defaults, translationOverwrite = {}) => {
const { language: languageProp, translation: overwrite } = translationOverwrite;
const { language: inferredLanguage } = useLanguage();
const usedLanguage = languageProp ?? inferredLanguage;
let defaultValues = defaults[usedLanguage];
if (overwrite && overwrite[usedLanguage]) {
defaultValues = { ...defaultValues, ...overwrite[usedLanguage] };
}
return defaultValues;
};
// src/components/Pagination.tsx
var import_jsx_runtime4 = require("react/jsx-runtime");
var defaultPaginationTranslations = {
en: {
of: "of"
},
de: {
of: "von"
}
};
var Pagination = ({
overwriteTranslation,
page,
numberOfPages,
onPageChanged
}) => {
const translation = useTranslation(defaultPaginationTranslations, overwriteTranslation);
const changePage = (page2) => {
onPageChanged(page2);
};
const noPages = numberOfPages === 0;
const onFirstPage = page === 0 && !noPages;
const onLastPage = page === numberOfPages - 1;
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: (0, import_clsx2.default)("row", { "opacity-30": noPages }), children: [
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { onClick: () => changePage(0), disabled: onFirstPage, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronFirst, { className: (0, import_clsx2.default)({ "opacity-30": onFirstPage }) }) }),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { onClick: () => changePage(page - 1), disabled: onFirstPage, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronLeft, { className: (0, import_clsx2.default)({ "opacity-30": onFirstPage }) }) }),
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "min-w-[80px] justify-center mx-2", children: [
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "select-none text-right flex-1", children: noPages ? 0 : page + 1 }),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "select-none mx-2", children: translation.of }),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "select-none text-left flex-1", children: numberOfPages })
] }),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { onClick: () => changePage(page + 1), disabled: onLastPage || noPages, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronRight, { className: (0, import_clsx2.default)({ "opacity-30": onLastPage }) }) }),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { onClick: () => changePage(numberOfPages - 1), disabled: onLastPage || noPages, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronLast, { className: (0, import_clsx2.default)({ "opacity-30": onLastPage }) }) })
] });
};
// src/components/Table.tsx
var import_clsx3 = __toESM(require("clsx"));
var import_jsx_runtime5 = require("react/jsx-runtime");
var defaultTableStatePagination = {
currentPage: 0,
entriesPerPage: 5
};
var defaultTableStateSelection = {
currentSelection: [],
hasSelectedAll: false,
hasSelectedSome: false,
hasSelectedNone: true
};
var isDataObjectSelected = (tableState, dataObject, identifierMapping) => {
if (!tableState.selection) {
return false;
}
return !!tableState.selection.currentSelection.find((value) => value.localeCompare(identifierMapping(dataObject)) === 0);
};
var pageForItem = (data, item, entriesPerPage, identifierMapping) => {
const index = data.findIndex((value) => identifierMapping(value) === identifierMapping(item));
if (index !== -1) {
return Math.floor(index / entriesPerPage);
}
console.warn("item doesn't exist on data", item, data);
return 0;
};
var updatePagination = (pagination, dataLength) => ({
...pagination,
currentPage: Math.min(Math.max(Math.ceil(dataLength / pagination.entriesPerPage) - 1, 0), pagination.currentPage)
});
var addElementToTable = (tableState, data, dataObject, identifierMapping) => {
return {
...tableState,
pagination: tableState.pagination ? {
...tableState.pagination,
currentPage: pageForItem(data, dataObject, tableState.pagination.entriesPerPage, identifierMapping)
} : void 0,
selection: tableState.selection ? {
...tableState.selection,
hasSelectedAll: false,
hasSelectedSome: tableState.selection.hasSelectedAll || tableState.selection.hasSelectedSome
} : void 0
};
};
var removeFromTableSelection = (tableState, deletedObjects, dataLength, identifierMapping) => {
if (!tableState.selection) {
return tableState;
}
const deletedObjectIds = deletedObjects.map(identifierMapping);
const elementsBefore = tableState.selection.currentSelection.length;
const currentSelection = tableState.selection.currentSelection.filter((value) => !deletedObjectIds.includes(value));
dataLength -= elementsBefore - currentSelection.length;
return {
...tableState,
selection: {
currentSelection,
hasSelectedAll: currentSelection.length === dataLength && dataLength !== 0,
hasSelectedSome: currentSelection.length > 0 && currentSelection.length !== dataLength,
hasSelectedNone: currentSelection.length === 0
},
pagination: tableState.pagination ? updatePagination(tableState.pagination, dataLength) : void 0
};
};
var changeTableSelectionSingle = (tableState, dataObject, dataLength, identifierMapping) => {
if (!tableState.selection) {
return tableState;
}
const hasSelectedObject = isDataObjectSelected(tableState, dataObject, identifierMapping);
let currentSelection = [...tableState.selection.currentSelection, identifierMapping(dataObject)];
if (hasSelectedObject) {
currentSelection = tableState.selection.currentSelection.filter((value) => value.localeCompare(identifierMapping(dataObject)) !== 0);
}
return {
...tableState,
selection: {
currentSelection,
hasSelectedAll: currentSelection.length === dataLength,
hasSelectedSome: currentSelection.length > 0 && currentSelection.length !== dataLength,
hasSelectedNone: currentSelection.length === 0
}
};
};
var changeTableSelectionAll = (tableState, data, identifierMapping) => {
if (!tableState.selection) {
return tableState;
}
if (data.length === 0) {
return {
...tableState,
selection: {
currentSelection: [],
hasSelectedAll: false,
hasSelectedSome: false,
hasSelectedNone: true
}
};
}
const hasSelectedAll = !(tableState.selection.hasSelectedSome || tableState.selection.hasSelectedAll);
return {
...tableState,
selection: {
currentSelection: hasSelectedAll ? data.map(identifierMapping) : [],
hasSelectedAll,
hasSelectedSome: false,
hasSelectedNone: !hasSelectedAll
}
};
};
var Table = ({
data,
stateManagement = [{}, noop],
identifierMapping,
header,
rowMappingToCells,
sorting,
focusElement,
className
}) => {
const sortedData = [...data];
if (sorting) {
const [sortingFunction, sortingType] = sorting;
sortedData.sort((a, b) => sortingFunction(a, b) * (sortingType === "ascending" ? 1 : -1));
}
let currentPage = 0;
let pageCount = 1;
let entriesPerPage = 5;
const [tableState, updateTableState] = stateManagement;
let shownElements = sortedData;
if (tableState?.pagination) {
if (tableState.pagination.entriesPerPage < 1) {
console.error("tableState.pagination.entriesPerPage must be >= 1", tableState.pagination.entriesPerPage);
}
entriesPerPage = Math.max(1, tableState.pagination.entriesPerPage);
pageCount = Math.ceil(sortedData.length / entriesPerPage);
if (tableState.pagination.currentPage < 0 || tableState.pagination.currentPage >= pageCount && pageCount !== 0) {
console.error(
"tableState.pagination.currentPage < 0 || (tableState.pagination.currentPage >= pageCount && pageCount !== 0) must be fullfilled",
[`pageCount: ${pageCount}`, `tableState.pagination.currentPage: ${tableState.pagination.currentPage}`]
);
} else {
currentPage = tableState.pagination.currentPage;
}
if (focusElement) {
currentPage = pageForItem(sortedData, focusElement, entriesPerPage, identifierMapping);
}
shownElements = sortedData.slice(currentPage * entriesPerPage, Math.min(sortedData.length, (currentPage + 1) * entriesPerPage));
} else {
currentPage = 0;
}
const headerRow = "border-b-2 border-gray-300";
const headerPaddingHead = "pb-2";
const headerPaddingBody = "pt-2";
const cellPadding = "py-1 px-2";
const [scrollbarsAutoHeightMin, setScrollbarsAutoHeightMin] = (0, import_react4.useState)(0);
const tableRef = (0, import_react4.useRef)(null);
const calculateHeight = () => {
if (tableRef.current) {
const tableHeight = tableRef.current.offsetHeight;
const offset = 25;
setScrollbarsAutoHeightMin(tableHeight + offset);
}
};
(0, import_react4.useEffect)(() => {
calculateHeight();
const handleResize = () => {
calculateHeight();
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [data, currentPage]);
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: (0, import_clsx3.default)("col gap-y-4 overflow-hidden", className), children: [
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_custom_scrollbars_2.Scrollbars, { autoHeight: true, autoHeightMin: scrollbarsAutoHeightMin, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { ref: tableRef, className: "w-full mb-[12px]", children: [
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: headerRow, children: [
header && tableState.selection && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: headerPaddingHead, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
ControlledCheckbox,
{
checked: tableState.selection.hasSelectedSome ? "indeterminate" : tableState.selection.hasSelectedAll,
onChange: () => updateTableState(changeTableSelectionAll(tableState, data, identifierMapping))
}
) }),
header && header.map((value, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: headerPaddingHead, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "row justify-start px-2", children: value }) }, `tableHeader${index}`))
] }) }),
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: shownElements.map((value, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
tableState.selection && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: (0, import_clsx3.default)(cellPadding, { [headerPaddingBody]: rowIndex === 0 }), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
ControlledCheckbox,
{
checked: isDataObjectSelected(tableState, value, identifierMapping),
onChange: () => {
updateTableState(changeTableSelectionSingle(tableState, value, data.length, identifierMapping));
}
}
) }),
rowMappingToCells(value).map((value1, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: (0, import_clsx3.default)(cellPadding, { [headerPaddingBody]: rowIndex === 0 }), children: value1 }, index))
] }, identifierMapping(value))) })
] }) }) }),
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "row justify-center", children: tableState.pagination && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Pagination, { page: currentPage, numberOfPages: pageCount, onPageChanged: (page) => updateTableState({
...tableState,
pagination: { entriesPerPage, currentPage: page }
}) }) })
] });
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Table,
addElementToTable,
changeTableSelectionSingle,
defaultTableStatePagination,
defaultTableStateSelection,
isDataObjectSelected,
pageForItem,
removeFromTableSelection,
updatePagination
});
//# sourceMappingURL=Table.js.map