diff --git a/CHANGELOG.md b/CHANGELOG.md index 644b17f..4d2a0c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v0.3.1] - 2026-05-30 + +### Fixed + +- Toast IDs no longer use `crypto.randomUUID()` (requires HTTPS/localhost). IDs are generated with a counter + timestamp via `createToastId()` so toasts work over HTTP in Docker and other non-secure contexts. + +### Changed + +- `@maks-it.com/webui-components`: shared helpers (`debounce`, `colSpanClass`, `GridColSpan`) are imported from the `functions` barrel instead of subpaths. +- `@maks-it.com/webui-core`: re-exports `date-fns` primitives (`parseISO`, `formatISO`, `format`, `getDaysInMonth`, `addMonths`, `subMonths`) for consumers. +- `@maks-it.com/webui-components` `DateTimePickerComponent` imports date helpers from `@maks-it.com/webui-core` instead of `date-fns` directly. + +### Removed + +- `lodash` and `@types/lodash` from `@maks-it.com/webui-components`; filter debouncing uses a local `debounce()` helper. +- Duplicate `date-fns` dependency from `@maks-it.com/webui-components` (`date-fns` remains on `@maks-it.com/webui-core` only). + ## [v0.3.0] - 2026-05-25 ### Added diff --git a/assets/badges/coverage-lines.svg b/assets/badges/coverage-lines.svg index fc05df3..dba109a 100644 --- a/assets/badges/coverage-lines.svg +++ b/assets/badges/coverage-lines.svg @@ -1,21 +1,21 @@ - - Line Coverage: 42.7% + + Line Coverage: 42% - + - - + + Line Coverage - - 42.7% + + 42% diff --git a/assets/badges/coverage-methods.svg b/assets/badges/coverage-methods.svg index e14bb74..7789289 100644 --- a/assets/badges/coverage-methods.svg +++ b/assets/badges/coverage-methods.svg @@ -1,5 +1,5 @@ - - Method Coverage: 21.5% + + Method Coverage: 20.3% @@ -15,7 +15,7 @@ Method Coverage - - 21.5% + + 20.3% diff --git a/src/coverage/coverage-summary.json b/src/coverage/coverage-summary.json index 753ab90..604cb58 100644 --- a/src/coverage/coverage-summary.json +++ b/src/coverage/coverage-summary.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":824,"covered":352,"skipped":0,"pct":42.71},"statements":{"total":889,"covered":377,"skipped":0,"pct":42.4},"functions":{"total":200,"covered":43,"skipped":0,"pct":21.5},"branches":{"total":404,"covered":194,"skipped":0,"pct":48.01},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":837,"covered":352,"skipped":0,"pct":42.05},"statements":{"total":902,"covered":377,"skipped":0,"pct":41.79},"functions":{"total":212,"covered":43,"skipped":0,"pct":20.28},"branches":{"total":404,"covered":194,"skipped":0,"pct":48.01},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\contracts\\src\\PagedRequest.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\contracts\\src\\PatchOperation.ts": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\contracts\\src\\PatchRequestModelBase.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -9,7 +9,7 @@ ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\contracts\\src\\identity\\login\\RefreshTokenRequest.ts": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\contracts\\src\\identity\\logout\\LogoutRequest.ts": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\index.ts": {"lines":{"total":5,"covered":0,"skipped":0,"pct":0},"functions":{"total":4,"covered":0,"skipped":0,"pct":0},"statements":{"total":9,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\index.ts": {"lines":{"total":41,"covered":0,"skipped":0,"pct":0},"functions":{"total":32,"covered":0,"skipped":0,"pct":0},"statements":{"total":41,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\index.ts": {"lines":{"total":47,"covered":0,"skipped":0,"pct":0},"functions":{"total":38,"covered":0,"skipped":0,"pct":0},"statements":{"total":47,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\acl\\index.ts": {"lines":{"total":1,"covered":0,"skipped":0,"pct":0},"functions":{"total":2,"covered":0,"skipped":0,"pct":0},"statements":{"total":3,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\acl\\parseAclEntry.ts": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":18,"covered":18,"skipped":0,"pct":100},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\dataTable\\dataTableFilters.ts": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} @@ -17,7 +17,7 @@ ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\dataTable\\index.ts": {"lines":{"total":4,"covered":0,"skipped":0,"pct":0},"functions":{"total":2,"covered":0,"skipped":0,"pct":0},"statements":{"total":4,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\date\\dateTimeToUtcIsoSchema.ts": {"lines":{"total":8,"covered":0,"skipped":0,"pct":0},"functions":{"total":2,"covered":0,"skipped":0,"pct":0},"statements":{"total":8,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\date\\formatISODateString.ts": {"lines":{"total":10,"covered":0,"skipped":0,"pct":0},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":10,"covered":0,"skipped":0,"pct":0},"branches":{"total":4,"covered":0,"skipped":0,"pct":0}} -,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\date\\index.ts": {"lines":{"total":5,"covered":0,"skipped":0,"pct":0},"functions":{"total":3,"covered":0,"skipped":0,"pct":0},"statements":{"total":6,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\date\\index.ts": {"lines":{"total":12,"covered":0,"skipped":0,"pct":0},"functions":{"total":9,"covered":0,"skipped":0,"pct":0},"statements":{"total":13,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\date\\isValidDateString.ts": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\deep\\deepCopy.ts": {"lines":{"total":17,"covered":16,"skipped":0,"pct":94.11},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":17,"covered":16,"skipped":0,"pct":94.11},"branches":{"total":12,"covered":11,"skipped":0,"pct":91.66}} ,"E:\\Users\\maksym\\source\\repos\\MaksIT\\maksit-webui\\src\\packages\\core\\src\\functions\\deep\\deepDelta.ts": {"lines":{"total":183,"covered":119,"skipped":0,"pct":65.02},"functions":{"total":18,"covered":14,"skipped":0,"pct":77.77},"statements":{"total":199,"covered":130,"skipped":0,"pct":65.32},"branches":{"total":137,"covered":92,"skipped":0,"pct":67.15}} diff --git a/src/package-lock.json b/src/package-lock.json index 736d06b..1d5bcb6 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "maksit-webui", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "maksit-webui", - "version": "0.3.0", + "version": "0.3.1", "license": "MIT", "workspaces": [ "packages/*" @@ -3520,13 +3520,6 @@ "pretty-format": "^30.0.0" } }, - "node_modules/@types/lodash": { - "version": "4.17.24", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", - "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/mdx": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", @@ -7234,12 +7227,6 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", - "license": "MIT" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -10427,24 +10414,21 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "packages/components": { "name": "@maks-it.com/webui-components", - "version": "0.3.0", + "version": "0.3.1", "dependencies": { - "@maks-it.com/webui-contracts": "^0.3.0", - "@maks-it.com/webui-core": "^0.3.0", - "date-fns": "^4.3.0", - "lodash": "^4.18.1" + "@maks-it.com/webui-contracts": "^0.3.1", + "@maks-it.com/webui-core": "^0.3.1" }, "devDependencies": { "@tanstack/react-table": "^8.21.3", - "@types/lodash": "^4.17.24", "@types/react": "^19.2.15", "@types/react-dom": "^19.2.3", "@types/react-virtualized": "^9.22.3", @@ -10469,7 +10453,7 @@ }, "packages/contracts": { "name": "@maks-it.com/webui-contracts", - "version": "0.3.0", + "version": "0.3.1", "devDependencies": { "tsup": "^8.5.1", "typescript": "^6.0.3", @@ -10481,9 +10465,9 @@ }, "packages/core": { "name": "@maks-it.com/webui-core", - "version": "0.3.0", + "version": "0.3.1", "dependencies": { - "@maks-it.com/webui-contracts": "^0.3.0", + "@maks-it.com/webui-contracts": "^0.3.1", "date-fns": "^4.3.0" }, "devDependencies": { diff --git a/src/package.json b/src/package.json index f335885..c285b53 100644 --- a/src/package.json +++ b/src/package.json @@ -1,7 +1,7 @@ { "name": "maksit-webui", "private": true, - "version": "0.3.0", + "version": "0.3.1", "description": "Shared React UI library for MaksIT Certs UI and Vault WebUI", "workspaces": [ "packages/*" diff --git a/src/packages/components/package.json b/src/packages/components/package.json index 75c1b4f..0746fcc 100644 --- a/src/packages/components/package.json +++ b/src/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@maks-it.com/webui-components", - "version": "0.3.0", + "version": "0.3.1", "description": "Shared React components for MaksIT WebUI apps", "type": "module", "main": "./dist/index.cjs", @@ -33,10 +33,8 @@ "directory": "src/packages/components" }, "dependencies": { - "@maks-it.com/webui-contracts": "^0.3.0", - "@maks-it.com/webui-core": "^0.3.0", - "date-fns": "^4.3.0", - "lodash": "^4.18.1" + "@maks-it.com/webui-contracts": "^0.3.1", + "@maks-it.com/webui-core": "^0.3.1" }, "peerDependencies": { "@tanstack/react-table": "^8.0.0", @@ -49,7 +47,6 @@ }, "devDependencies": { "@tanstack/react-table": "^8.21.3", - "@types/lodash": "^4.17.24", "@types/react": "^19.2.15", "@types/react-dom": "^19.2.3", "@types/react-virtualized": "^9.22.3", diff --git a/src/packages/components/src/components/DataTable/DataTable.tsx b/src/packages/components/src/components/DataTable/DataTable.tsx index 0866359..a5e120b 100644 --- a/src/packages/components/src/components/DataTable/DataTable.tsx +++ b/src/packages/components/src/components/DataTable/DataTable.tsx @@ -3,8 +3,7 @@ import { AutoSizer, MultiGrid, GridCellProps } from 'react-virtualized' import { mapPagedToDataTable, type DataTablePageView, type PagedResponse } from '@maks-it.com/webui-core' import { Plus, Trash2, Edit } from 'lucide-react' -import debounce from 'lodash/debounce' -import { colSpanClass, type GridColSpan } from '../../functions/tailwind' +import { debounce, colSpanClass, type GridColSpan } from '../../functions' interface FilterProps { diff --git a/src/packages/components/src/components/DataTable/DataTableFilter.tsx b/src/packages/components/src/components/DataTable/DataTableFilter.tsx index 33e5f58..67b87f2 100644 --- a/src/packages/components/src/components/DataTable/DataTableFilter.tsx +++ b/src/packages/components/src/components/DataTable/DataTableFilter.tsx @@ -1,5 +1,5 @@ import { useMemo, useState } from 'react' -import debounce from 'lodash/debounce' +import { debounce } from '../../functions' interface FilterPropsBase { filterId?: string diff --git a/src/packages/components/src/components/LazyLoadTable.tsx b/src/packages/components/src/components/LazyLoadTable.tsx index 9aa6f44..cbf6aad 100644 --- a/src/packages/components/src/components/LazyLoadTable.tsx +++ b/src/packages/components/src/components/LazyLoadTable.tsx @@ -1,5 +1,5 @@ import { FC, type ReactNode, useEffect, useRef, useState } from 'react' -import { colSpanClass, type GridColSpan } from '../functions/tailwind' +import { colSpanClass, type GridColSpan } from '../functions' interface LazyLoadTableColumnProps { key: string diff --git a/src/packages/components/src/components/Offcanvas.tsx b/src/packages/components/src/components/Offcanvas.tsx index ee4df3c..830124c 100644 --- a/src/packages/components/src/components/Offcanvas.tsx +++ b/src/packages/components/src/components/Offcanvas.tsx @@ -1,5 +1,5 @@ import { FC, ReactNode, useCallback, useEffect } from 'react' -import { colSpanClass, type GridColSpan } from '../functions/tailwind' +import { colSpanClass, type GridColSpan } from '../functions' export interface OffcanvasProps { children: ReactNode diff --git a/src/packages/components/src/components/Toast/createToastId.ts b/src/packages/components/src/components/Toast/createToastId.ts new file mode 100644 index 0000000..4d71bca --- /dev/null +++ b/src/packages/components/src/components/Toast/createToastId.ts @@ -0,0 +1,7 @@ +let toastIdSeq = 0 + +/** Works on plain HTTP; crypto.randomUUID() requires a secure context. */ +export const createToastId = (): string => { + toastIdSeq += 1 + return `toast-${toastIdSeq}-${Date.now()}` +} diff --git a/src/packages/components/src/components/Toast/index.tsx b/src/packages/components/src/components/Toast/index.tsx index 7934fb1..d4c13cb 100644 --- a/src/packages/components/src/components/Toast/index.tsx +++ b/src/packages/components/src/components/Toast/index.tsx @@ -1,4 +1,5 @@ import { useState, useEffect, FC } from 'react' +import { createToastId } from './createToastId' // Define types for a toast interface Toast { @@ -8,8 +9,6 @@ interface Toast { duration?: number; } -const createToastId = (): string => crypto.randomUUID() - const Toast: FC = () => { const [toasts, setToasts] = useState([]) diff --git a/src/packages/components/src/components/editors/ButtonComponent.tsx b/src/packages/components/src/components/editors/ButtonComponent.tsx index a950565..36888ea 100644 --- a/src/packages/components/src/components/editors/ButtonComponent.tsx +++ b/src/packages/components/src/components/editors/ButtonComponent.tsx @@ -1,6 +1,6 @@ import { type FC, type MouseEvent, type ReactNode } from 'react' import { Link } from 'react-router-dom' -import { colSpanClass, type GridColSpan } from '../../functions/tailwind' +import { colSpanClass, type GridColSpan } from '../../functions' interface CommonButtonProps { colspan?: GridColSpan; diff --git a/src/packages/components/src/components/editors/CheckBoxComponent.tsx b/src/packages/components/src/components/editors/CheckBoxComponent.tsx index 3f512ec..e68d8d5 100644 --- a/src/packages/components/src/components/editors/CheckBoxComponent.tsx +++ b/src/packages/components/src/components/editors/CheckBoxComponent.tsx @@ -1,5 +1,5 @@ import { type ChangeEvent, type FC, useEffect, useRef } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' interface CheckBoxComponentProps { diff --git a/src/packages/components/src/components/editors/DateTimePickerComponent.tsx b/src/packages/components/src/components/editors/DateTimePickerComponent.tsx index 68d78a1..b32d915 100644 --- a/src/packages/components/src/components/editors/DateTimePickerComponent.tsx +++ b/src/packages/components/src/components/editors/DateTimePickerComponent.tsx @@ -1,9 +1,16 @@ import { ChangeEvent, FC, useState, useEffect, useRef } from 'react' -import { parseISO, formatISO, format, getDaysInMonth, addMonths, subMonths } from 'date-fns' +import { + parseISO, + formatISO, + format, + getDaysInMonth, + addMonths, + subMonths, +} from '@maks-it.com/webui-core' +import { CircleX } from 'lucide-react' import { ButtonComponent } from './ButtonComponent' import { TextBoxComponent } from './TextBoxComponent' -import { CircleX } from 'lucide-react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' import { getInputClasses } from './editorStyles' diff --git a/src/packages/components/src/components/editors/DualListboxComponent.tsx b/src/packages/components/src/components/editors/DualListboxComponent.tsx index 82c9c1b..ec6232e 100644 --- a/src/packages/components/src/components/editors/DualListboxComponent.tsx +++ b/src/packages/components/src/components/editors/DualListboxComponent.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' interface DualListboxComponentProps { diff --git a/src/packages/components/src/components/editors/FieldContainer.tsx b/src/packages/components/src/components/editors/FieldContainer.tsx index afbc5c0..e5e5ffc 100644 --- a/src/packages/components/src/components/editors/FieldContainer.tsx +++ b/src/packages/components/src/components/editors/FieldContainer.tsx @@ -1,5 +1,5 @@ import { FC, ReactNode } from 'react' -import { colSpanClass, type GridColSpan } from '../../functions/tailwind' +import { colSpanClass, type GridColSpan } from '../../functions' interface FieldContainerProps { colspan?: GridColSpan; diff --git a/src/packages/components/src/components/editors/FileUploadComponent.tsx b/src/packages/components/src/components/editors/FileUploadComponent.tsx index 32d71b4..ba1963e 100644 --- a/src/packages/components/src/components/editors/FileUploadComponent.tsx +++ b/src/packages/components/src/components/editors/FileUploadComponent.tsx @@ -1,5 +1,5 @@ import React, { useRef, useState } from 'react' -import { colSpanClass, type GridColSpan } from '../../functions/tailwind' +import { colSpanClass, type GridColSpan } from '../../functions' import { ButtonComponent } from './ButtonComponent' import { Trash2 } from 'lucide-react' diff --git a/src/packages/components/src/components/editors/ListBoxComponent.tsx b/src/packages/components/src/components/editors/ListBoxComponent.tsx index 1e1c2d6..73e02e7 100644 --- a/src/packages/components/src/components/editors/ListBoxComponent.tsx +++ b/src/packages/components/src/components/editors/ListBoxComponent.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' interface ListboxComponentProps { diff --git a/src/packages/components/src/components/editors/RadioGroupComponent.tsx b/src/packages/components/src/components/editors/RadioGroupComponent.tsx index 012af4b..ea46d5e 100644 --- a/src/packages/components/src/components/editors/RadioGroupComponent.tsx +++ b/src/packages/components/src/components/editors/RadioGroupComponent.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' interface RadioOption { diff --git a/src/packages/components/src/components/editors/RemoteSelectBoxComponent.tsx b/src/packages/components/src/components/editors/RemoteSelectBoxComponent.tsx index 5dfa969..aadc9e3 100644 --- a/src/packages/components/src/components/editors/RemoteSelectBoxComponent.tsx +++ b/src/packages/components/src/components/editors/RemoteSelectBoxComponent.tsx @@ -2,7 +2,7 @@ import { useState, useCallback, ChangeEvent, useEffect, useRef } from 'react' import type { PagedRequest } from '@maks-it.com/webui-contracts' import type { SearchResponseBase } from '@maks-it.com/webui-contracts' import { deepEqual } from '@maks-it.com/webui-core' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { SelectBoxComponent } from './SelectBoxComponent' export type RemoteSelectSearchDataSource = ( diff --git a/src/packages/components/src/components/editors/SecretComponent.tsx b/src/packages/components/src/components/editors/SecretComponent.tsx index 5d6254c..e5cf42a 100644 --- a/src/packages/components/src/components/editors/SecretComponent.tsx +++ b/src/packages/components/src/components/editors/SecretComponent.tsx @@ -1,6 +1,6 @@ import { Copy, Dices, Eye, EyeOff } from 'lucide-react' import { ChangeEvent, FC, useRef, useState } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' import { getInputClasses } from './editorStyles' diff --git a/src/packages/components/src/components/editors/SelectBoxComponent.tsx b/src/packages/components/src/components/editors/SelectBoxComponent.tsx index afc1fcb..6e78894 100644 --- a/src/packages/components/src/components/editors/SelectBoxComponent.tsx +++ b/src/packages/components/src/components/editors/SelectBoxComponent.tsx @@ -1,7 +1,6 @@ -import debounce from 'lodash/debounce' import { CircleX } from 'lucide-react' import { ChangeEvent, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import { debounce, type GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' import { getInputClasses } from './editorStyles' diff --git a/src/packages/components/src/components/editors/TextBoxComponent.tsx b/src/packages/components/src/components/editors/TextBoxComponent.tsx index bb70a2d..3f85fb3 100644 --- a/src/packages/components/src/components/editors/TextBoxComponent.tsx +++ b/src/packages/components/src/components/editors/TextBoxComponent.tsx @@ -1,6 +1,6 @@ import { Eye, EyeOff } from 'lucide-react' import { ChangeEvent, FC, useEffect, useRef, useState } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' import { getInputClasses } from './editorStyles' diff --git a/src/packages/components/src/components/editors/TreeViewComponent.tsx b/src/packages/components/src/components/editors/TreeViewComponent.tsx index c82c5bc..18ac10d 100644 --- a/src/packages/components/src/components/editors/TreeViewComponent.tsx +++ b/src/packages/components/src/components/editors/TreeViewComponent.tsx @@ -1,5 +1,5 @@ import React, { useState, ReactNode } from 'react' -import type { GridColSpan } from '../../functions/tailwind' +import type { GridColSpan } from '../../functions' import { FieldContainer } from './FieldContainer' interface TreeNode { diff --git a/src/packages/components/src/functions/debounce.ts b/src/packages/components/src/functions/debounce.ts new file mode 100644 index 0000000..c82c9e3 --- /dev/null +++ b/src/packages/components/src/functions/debounce.ts @@ -0,0 +1,17 @@ +/** Trailing-edge debounce; lodash/debounce was only used for this pattern. */ +export const debounce = ( + fn: (...args: Args) => void, + waitMs: number +): ((...args: Args) => void) => { + let timeoutId: ReturnType | undefined + + return (...args: Args) => { + if (timeoutId !== undefined) { + clearTimeout(timeoutId) + } + timeoutId = setTimeout(() => { + timeoutId = undefined + fn(...args) + }, waitMs) + } +} diff --git a/src/packages/components/src/functions/index.ts b/src/packages/components/src/functions/index.ts index 2af7a6d..351e9e4 100644 --- a/src/packages/components/src/functions/index.ts +++ b/src/packages/components/src/functions/index.ts @@ -1,2 +1,3 @@ +export { debounce } from './debounce' export { colSpanClass } from './tailwind' export type { GridColSpan } from './tailwind' diff --git a/src/packages/contracts/package.json b/src/packages/contracts/package.json index 27c8536..1b1adc4 100644 --- a/src/packages/contracts/package.json +++ b/src/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@maks-it.com/webui-contracts", - "version": "0.3.0", + "version": "0.3.1", "description": "Shared TypeScript contracts for MaksIT WebUI apps", "type": "module", "main": "./dist/index.cjs", diff --git a/src/packages/core/package.json b/src/packages/core/package.json index 1037876..103c37c 100644 --- a/src/packages/core/package.json +++ b/src/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@maks-it.com/webui-core", - "version": "0.3.0", + "version": "0.3.1", "description": "Shared utilities and hooks for MaksIT WebUI apps", "type": "module", "main": "./dist/index.cjs", @@ -34,7 +34,7 @@ "directory": "src/packages/core" }, "dependencies": { - "@maks-it.com/webui-contracts": "^0.3.0", + "@maks-it.com/webui-contracts": "^0.3.1", "date-fns": "^4.3.0" }, "peerDependencies": { diff --git a/src/packages/core/src/functions/date/index.ts b/src/packages/core/src/functions/date/index.ts index 54874f3..e2c7e66 100644 --- a/src/packages/core/src/functions/date/index.ts +++ b/src/packages/core/src/functions/date/index.ts @@ -5,5 +5,14 @@ export { dateTimeToUtcIsoSchema } from './dateTimeToUtcIsoSchema' export { isValidISODateString, - formatISODateString -} \ No newline at end of file + formatISODateString, +} + +export { + parseISO, + formatISO, + format, + getDaysInMonth, + addMonths, + subMonths, +} from 'date-fns' \ No newline at end of file diff --git a/src/packages/core/src/functions/index.ts b/src/packages/core/src/functions/index.ts index d347a0f..c5fa51f 100644 --- a/src/packages/core/src/functions/index.ts +++ b/src/packages/core/src/functions/index.ts @@ -2,6 +2,12 @@ import { isValidISODateString, formatISODateString, dateTimeToUtcIsoSchema, + parseISO, + formatISO, + format, + getDaysInMonth, + addMonths, + subMonths, } from './date' import { @@ -47,6 +53,12 @@ export { isValidISODateString, formatISODateString, dateTimeToUtcIsoSchema, + parseISO, + formatISO, + format, + getDaysInMonth, + addMonths, + subMonths, deepCopy, deepDelta, deltaHasOperations, diff --git a/src/stories/components/Offcanvas.stories.tsx b/src/stories/components/Offcanvas.stories.tsx index d9e5490..cb20d38 100644 --- a/src/stories/components/Offcanvas.stories.tsx +++ b/src/stories/components/Offcanvas.stories.tsx @@ -2,7 +2,7 @@ import { useState, type JSX, type ReactNode } from 'react' import type { Meta, StoryObj } from '@storybook/react-vite' import { fn } from 'storybook/test' import { ButtonComponent } from '@webui/components/components/editors/ButtonComponent' -import type { GridColSpan } from '@webui/components/functions/tailwind' +import type { GridColSpan } from '@webui/components/functions' import { Offcanvas } from '@webui/components/components/Offcanvas' import { FormContainer } from '@webui/components/components/FormLayout/FormContainer' import { FormContent } from '@webui/components/components/FormLayout/FormContent' diff --git a/src/vitest.config.ts b/src/vitest.config.ts index 2381512..70bc452 100644 --- a/src/vitest.config.ts +++ b/src/vitest.config.ts @@ -19,7 +19,6 @@ export default defineConfig({ 'react-router-dom', 'storybook/test', 'lucide-react', - 'lodash/debounce', ], }, resolve: {