@itcase/ui-core 1.10.47 → 1.10.48

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.
Files changed (64) hide show
  1. package/dist/cjs/context/Notifications.interface.js +2 -1
  2. package/dist/cjs/context/Notifications.js +207 -1
  3. package/dist/cjs/context/UIContext.js +76 -1
  4. package/dist/cjs/context/UrlAssetPrefix.js +17 -1
  5. package/dist/cjs/context/index.js +24 -1
  6. package/dist/cjs/hoc/index.js +11 -1
  7. package/dist/cjs/hoc/urlWithAssetPrefix.js +78 -1
  8. package/dist/cjs/hooks/index.js +37 -1
  9. package/dist/cjs/hooks/useActiveClasses/index.js +9 -1
  10. package/dist/cjs/hooks/useActiveClasses/useActiveClasses.helpers.js +93 -1
  11. package/dist/cjs/hooks/useActiveClasses/useActiveClasses.interface.js +65 -1
  12. package/dist/cjs/hooks/useActiveClasses/useActiveClasses.js +60 -1
  13. package/dist/cjs/hooks/useAppearanceConfig/index.js +8 -1
  14. package/dist/cjs/hooks/useAppearanceConfig/useAppearanceConfig.js +30 -1
  15. package/dist/cjs/hooks/useDevicePropsGenerator/index.js +23 -1
  16. package/dist/cjs/hooks/useDevicePropsGenerator/useDevicePropsGenerator.interface.js +2 -1
  17. package/dist/cjs/hooks/useDevicePropsGenerator/useDevicePropsGenerator.js +236 -1
  18. package/dist/cjs/hooks/useDeviceTargetClass.js +64 -1
  19. package/dist/cjs/hooks/useMediaQueries/index.js +9 -1
  20. package/dist/cjs/hooks/useMediaQueries/useMediaQueries.js +124 -1
  21. package/dist/cjs/hooks/useStyles/index.js +23 -1
  22. package/dist/cjs/hooks/useStyles/styleAttributes.helpers.js +9 -1
  23. package/dist/cjs/hooks/useStyles/styleAttributes.interface.js +2 -1
  24. package/dist/cjs/hooks/useStyles/styleAttributes.js +177 -1
  25. package/dist/cjs/hooks/useStyles/useStyles.js +224 -1
  26. package/dist/cjs/hooks/useViewportFix.js +43 -1
  27. package/dist/cjs/utils/index.js +9 -1
  28. package/dist/cjs/utils/mergeAppearanceKeys.js +18 -1
  29. package/dist/cjs/utils/setViewportProperty.js +8 -1
  30. package/dist/context/Notifications.js +202 -1
  31. package/dist/context/UIContext.js +73 -1
  32. package/dist/context/UrlAssetPrefix.js +14 -1
  33. package/dist/context/index.js +11 -1
  34. package/dist/hoc/index.js +5 -1
  35. package/dist/hoc/urlWithAssetPrefix.js +76 -1
  36. package/dist/hooks/index.js +24 -1
  37. package/dist/hooks/useActiveClasses/index.js +3 -1
  38. package/dist/hooks/useActiveClasses/useActiveClasses.helpers.js +89 -1
  39. package/dist/hooks/useActiveClasses/useActiveClasses.interface.js +63 -1
  40. package/dist/hooks/useActiveClasses/useActiveClasses.js +58 -1
  41. package/dist/hooks/useAppearanceConfig/index.js +2 -1
  42. package/dist/hooks/useAppearanceConfig/useAppearanceConfig.js +28 -1
  43. package/dist/hooks/useDevicePropsGenerator/index.js +17 -1
  44. package/dist/hooks/useDevicePropsGenerator/useDevicePropsGenerator.js +234 -1
  45. package/dist/hooks/useDeviceTargetClass.js +62 -1
  46. package/dist/hooks/useMediaQueries/index.js +3 -1
  47. package/dist/hooks/useMediaQueries/useMediaQueries.js +122 -1
  48. package/dist/hooks/useStyles/index.js +16 -1
  49. package/dist/hooks/useStyles/styleAttributes.helpers.js +7 -1
  50. package/dist/hooks/useStyles/styleAttributes.js +173 -1
  51. package/dist/hooks/useStyles/useStyles.js +222 -1
  52. package/dist/hooks/useViewportFix.js +41 -1
  53. package/dist/types/context/Notifications.d.ts +8 -8
  54. package/dist/types/hoc/urlWithAssetPrefix.d.ts +2 -3
  55. package/dist/types/hooks/useActiveClasses/useActiveClasses.interface.d.ts +4 -4
  56. package/dist/types/hooks/useAppearanceConfig/useAppearanceConfig.d.ts +1 -1
  57. package/dist/types/hooks/useDevicePropsGenerator/useDevicePropsGenerator.d.ts +1 -1
  58. package/dist/types/hooks/useDeviceTargetClass.d.ts +2 -1
  59. package/dist/types/hooks/useMediaQueries/useMediaQueries.d.ts +2 -1
  60. package/dist/types/hooks/useStyles/styleAttributes.helpers.d.ts +1 -1
  61. package/dist/utils/index.js +2 -1
  62. package/dist/utils/mergeAppearanceKeys.js +16 -1
  63. package/dist/utils/setViewportProperty.js +6 -1
  64. package/package.json +2 -2
@@ -1 +1,202 @@
1
- import{jsx as e}from"react/jsx-runtime";import{createContext as o,useState as i,useCallback as t,useMemo as r,useEffect as n,useContext as s}from"react";import{v4 as c}from"uuid";import{axiosInstanceITCase as a}from"@itcase/common";const l={error:"error",info:"info",success:"success",warning:"warning"},u=o([]),m=o({hideNotifications:e=>{},removeNotification:e=>{},showNotification:(e,o)=>{},notificationStatuses:l});function d(o){const{initialNotificationsList:s=[],isLogRequestsErrors:c,children:d}=o,[f,g]=i(()=>(s||[]).map(e=>y(e,e.onClose))),p=t(e=>{e&&g(o=>o.filter(o=>{const i=String(o.id)===String(e);return i&&(clearTimeout(o._closeTimeout),o.onClose&&o.onClose()),!i}))},[]),T=t(e=>{e&&g(o=>o.map(o=>String(o.id)!==String(e)||o.isClosing?o:(clearTimeout(o._closeTimeout),{...o,isClosing:!0})))},[]),S=t((e,o)=>{const i=y(e,o);return g(e=>{const o=e.slice(),t=o.findIndex(e=>String(e.id)===String(i.id));if(-1===t)return[...o,i];const r=o[t];return clearTimeout(r._closeTimeout),r._closeTimeout=void 0,o[t]=i,o}),i.closeByTime&&(i._closeTimeout=setTimeout(()=>T(i.id),i.closeByTime)),i},[]),B=r(()=>({hideNotifications:T,removeNotification:p,notificationStatuses:l,showNotification:S}),[]);return n(()=>{f.forEach(e=>{e.closeByTime&&setTimeout(()=>T(e.id),e.closeByTime)}),c&&(a.responseErrorHandler.loggerManager={log:e=>{if(e.message){const o=["network"].includes(e.key)?e.key:void 0;S({id:o,title:e.message,status:"error",closeByTime:4e3})}}})},[]),e(m.Provider,{value:B,children:e(u.Provider,{value:f,children:d})})}function f(){return s(u)}function g(){return s(m)}const p={error:"errorPrimary sizeS solid rounded",info:"infoPrimary sizeS solid rounded",success:"successPrimary sizeS solid rounded",warning:"warningPrimary sizeS solid rounded"};function y(e,o){let i=c().split("-")[0],t="",r="",n="",s="",a="float",u="",m=l.warning,d=4500,f=p[m],g=null,y=!1,T="",S=()=>{};return"string"==typeof e?r=e:"object"==typeof e&&(i=String(e.id??i),t=e.title??t,r=e.text??r,T=e.closeIconAppearance??T,a=e.type??a,n=e.closeIcon??n,s=e.closeIconSrc??s,u=e.buttonLabel??u,S=e.onClickButton??S,m=e.status??m,d=e.closeByTime??d,y=e.isLoading??y,g=e.after??g,f=e.appearance??p[e.status]??f),{id:i,appearance:f,type:a,title:t,status:m,text:r,buttonLabel:u,after:g,closeByTime:d,closeIcon:n,closeIconAppearance:T,closeIconSrc:s,isLoading:y,onClickButton:S,onClose:o}}export{d as NotificationsProvider,p as statusToAppearanceList,f as useNotifications,g as useNotificationsAPI};
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { createContext, useState, useCallback, useMemo, useEffect, useContext } from 'react';
4
+ import { v4 } from 'uuid';
5
+ import { axiosInstanceITCase } from '@itcase/common';
6
+
7
+ const STATUSES = {
8
+ error: 'error',
9
+ info: 'info',
10
+ success: 'success',
11
+ warning: 'warning',
12
+ };
13
+ const NotificationsContext = createContext([]);
14
+ /* eslint-disable @typescript-eslint/no-unused-vars */
15
+ const NotificationsAPIContext = createContext({
16
+ hideNotifications: (targetId) => { },
17
+ removeNotification: (targetId) => { },
18
+ showNotification: (notification, onClose) => { },
19
+ notificationStatuses: STATUSES,
20
+ });
21
+ /* eslint-enable @typescript-eslint/no-unused-vars */
22
+ function NotificationsProvider(props) {
23
+ const { initialNotificationsList = [], isLogRequestsErrors, children } = props;
24
+ const [notificationsList, setNotificationsList] = useState(() => {
25
+ // We need to set id to every notification item and original list also be have new id's
26
+ return (initialNotificationsList || []).map((notificationItem) => {
27
+ return createNotification(notificationItem, notificationItem.onClose);
28
+ });
29
+ });
30
+ const removeNotification = useCallback((targetId) => {
31
+ if (!targetId) {
32
+ return;
33
+ }
34
+ setNotificationsList((prevNotificationsList) => {
35
+ return prevNotificationsList.filter((notificationItem) => {
36
+ const isNeedToRemove = String(notificationItem.id) === String(targetId);
37
+ if (isNeedToRemove) {
38
+ clearTimeout(notificationItem._closeTimeout);
39
+ // @typescript-eslint/no-unused-expressions
40
+ notificationItem.onClose && notificationItem.onClose();
41
+ }
42
+ return !isNeedToRemove;
43
+ });
44
+ });
45
+ }, []);
46
+ const hideNotifications = useCallback((targetId) => {
47
+ if (!targetId) {
48
+ return;
49
+ }
50
+ setNotificationsList((prevNotificationsList) => {
51
+ return prevNotificationsList.map((notificationItem) => {
52
+ const isNeedToHide = String(notificationItem.id) === String(targetId);
53
+ if (!isNeedToHide || notificationItem.isClosing) {
54
+ return notificationItem;
55
+ }
56
+ clearTimeout(notificationItem._closeTimeout);
57
+ return {
58
+ ...notificationItem,
59
+ isClosing: true,
60
+ };
61
+ });
62
+ });
63
+ }, []);
64
+ const showNotification = useCallback((notification, onClose) => {
65
+ const newNotificationItem = createNotification(notification, onClose);
66
+ setNotificationsList((prevNotificationsList) => {
67
+ const newState = prevNotificationsList.slice();
68
+ const existsNotificationIndex = newState.findIndex((notificationItem) => String(notificationItem.id) === String(newNotificationItem.id));
69
+ // Add new notification
70
+ if (existsNotificationIndex === -1) {
71
+ return [...newState, newNotificationItem];
72
+ }
73
+ // Or update exists notification
74
+ const updatedNotificationItem = newState[existsNotificationIndex];
75
+ // Clear timeout to avoid close event for updated notification
76
+ clearTimeout(updatedNotificationItem._closeTimeout);
77
+ updatedNotificationItem._closeTimeout = undefined;
78
+ // Replace exists notification by new one
79
+ newState[existsNotificationIndex] = newNotificationItem;
80
+ return newState;
81
+ });
82
+ if (newNotificationItem.closeByTime) {
83
+ newNotificationItem._closeTimeout = setTimeout(() => hideNotifications(newNotificationItem.id), newNotificationItem.closeByTime);
84
+ }
85
+ return newNotificationItem;
86
+ },
87
+ // "hideNotifications" is never changed
88
+ // eslint-disable-next-line react-hooks/exhaustive-deps
89
+ []);
90
+ const notificationsAPI = useMemo(() => ({
91
+ hideNotifications: hideNotifications,
92
+ removeNotification: removeNotification,
93
+ notificationStatuses: STATUSES,
94
+ showNotification: showNotification,
95
+ }),
96
+ // Functions is never changes, no sense to set as dependencies
97
+ // eslint-disable-next-line
98
+ []);
99
+ useEffect(() => {
100
+ // Set timeout for initial notifications list one time on first render
101
+ notificationsList.forEach((notificationItem) => {
102
+ if (notificationItem.closeByTime) {
103
+ setTimeout(() => hideNotifications(notificationItem.id), notificationItem.closeByTime);
104
+ }
105
+ });
106
+ // Show notifications on all requests errors.
107
+ // Enable one time without disabling. Use "isLogging" on request config level
108
+ // to disable notifications logger.
109
+ if (isLogRequestsErrors) {
110
+ axiosInstanceITCase.responseErrorHandler.loggerManager = {
111
+ log: (responseError) => {
112
+ if (responseError.message) {
113
+ // prevent from showing many network errors
114
+ const errorListToDedupe = ['network'];
115
+ const id = errorListToDedupe.includes(responseError.key)
116
+ ? responseError.key
117
+ : undefined;
118
+ showNotification({
119
+ id: id,
120
+ title: responseError.message,
121
+ status: 'error',
122
+ closeByTime: 4000,
123
+ });
124
+ }
125
+ },
126
+ };
127
+ }
128
+ // eslint-disable-next-line react-hooks/exhaustive-deps
129
+ }, []);
130
+ return (jsx(NotificationsAPIContext.Provider, { value: notificationsAPI, children: jsx(NotificationsContext.Provider, { value: notificationsList, children: children }) }));
131
+ }
132
+ function useNotifications() {
133
+ return useContext(NotificationsContext);
134
+ }
135
+ function useNotificationsAPI() {
136
+ return useContext(NotificationsAPIContext);
137
+ }
138
+ const statusToAppearanceList = {
139
+ error: 'errorPrimary sizeS solid rounded',
140
+ info: 'infoPrimary sizeS solid rounded',
141
+ success: 'successPrimary sizeS solid rounded',
142
+ warning: 'warningPrimary sizeS solid rounded',
143
+ };
144
+ function createNotification(notification, onClose) {
145
+ // Default notification item properties
146
+ let id = v4().split('-')[0];
147
+ let title = '';
148
+ let text = '';
149
+ let closeIcon = '';
150
+ let closeIconSrc = '';
151
+ let type = 'float';
152
+ let buttonLabel = '';
153
+ let status = STATUSES.warning;
154
+ let closeByTime = 4500;
155
+ let appearance = statusToAppearanceList[status];
156
+ let after = null;
157
+ let isLoading = false;
158
+ let closeIconAppearance = '';
159
+ let onClickButton = () => { };
160
+ if (typeof notification === 'string') {
161
+ text = notification;
162
+ }
163
+ else if (typeof notification === 'object') {
164
+ id = String(notification.id ?? id);
165
+ title = notification.title ?? title;
166
+ text = notification.text ?? text;
167
+ closeIconAppearance =
168
+ notification.closeIconAppearance ?? closeIconAppearance;
169
+ type = notification.type ?? type;
170
+ closeIcon = notification.closeIcon ?? closeIcon;
171
+ closeIconSrc = notification.closeIconSrc ?? closeIconSrc;
172
+ buttonLabel = notification.buttonLabel ?? buttonLabel;
173
+ onClickButton = notification.onClickButton ?? onClickButton;
174
+ status = notification.status ?? status;
175
+ closeByTime = notification.closeByTime ?? closeByTime;
176
+ isLoading = notification.isLoading ?? isLoading;
177
+ after = notification.after ?? after;
178
+ appearance =
179
+ notification.appearance ??
180
+ statusToAppearanceList[notification.status] ??
181
+ appearance;
182
+ }
183
+ return {
184
+ id: id,
185
+ appearance: appearance,
186
+ type: type,
187
+ title: title,
188
+ status: status,
189
+ text: text,
190
+ buttonLabel: buttonLabel,
191
+ after: after,
192
+ closeByTime: closeByTime,
193
+ closeIcon: closeIcon,
194
+ closeIconAppearance: closeIconAppearance,
195
+ closeIconSrc: closeIconSrc,
196
+ isLoading: isLoading,
197
+ onClickButton: onClickButton,
198
+ onClose: onClose,
199
+ };
200
+ }
201
+
202
+ export { NotificationsProvider, statusToAppearanceList, useNotifications, useNotificationsAPI };
@@ -1 +1,73 @@
1
- import{jsx as e}from"react/jsx-runtime";import{createContext as r,memo as i,useMemo as t,useEffect as s,useContext as o}from"react";import n from"lodash/camelCase";import{useMediaQueries as c}from"../hooks/useMediaQueries/useMediaQueries.js";import{setViewportProperty as p}from"../utils/setViewportProperty.js";import"react-responsive";const a=r({isMobile:!1,isTablet:!1,isDesktop:!1,deviceCurrentMainType:"",deviceCurrentType:"",deviceTypesList:[]}),d=i(function(r){const{userDeviceState:i={},children:o}=r,d=c(i),{isMobile:u,isTablet:l,isDesktop:m,...v}=d,f=(u?"mobile":l&&"tablet")||m&&"desktop"||"",[y,b]=t(()=>{const e=Object.keys(d).map(e=>n(e.replace("is","")));let r=Object.keys(v).find(e=>v[e]);return r||(r=f),r=n(r.replace("is","")),[r||"_none_",e]},[d,f,v]),T=t(()=>({...d,deviceCurrentMainType:f,deviceCurrentType:y,deviceTypesList:b}),[d,f,y,b]);return s(()=>{p(),window.addEventListener("resize",p)},[]),e(a.Provider,{value:T,children:o})});function u(){const e=o(a);if(!e)throw new Error("useUserDeviceContext is not defined");return e}export{d as UIProvider,u as useUserDeviceContext};
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { createContext, memo, useMemo, useEffect, useContext } from 'react';
4
+ import camelCase from 'lodash/camelCase';
5
+ import { useMediaQueries } from '../hooks/useMediaQueries/useMediaQueries.js';
6
+ import { setViewportProperty } from '../utils/setViewportProperty.js';
7
+ import 'react-responsive';
8
+
9
+ const UserDeviceContext = createContext({
10
+ isMobile: false,
11
+ isTablet: false,
12
+ isDesktop: false,
13
+ deviceCurrentMainType: '',
14
+ deviceCurrentType: '',
15
+ deviceTypesList: [],
16
+ });
17
+ const UIProvider = memo(function UIProvider(props) {
18
+ const { userDeviceState = {}, children } = props;
19
+ /** NOTE:
20
+ * Remember that the "useMediaQueries" hook works by next scenario:
21
+ * when changing the device type(browser width), the hook will first "enable"
22
+ * the new type(set true), and then "disable" the previous one(set false),
23
+ * what provoke to double rendering, and in moment we have two different types as "true".
24
+ * We will need to look at how to change this behavior.
25
+ */
26
+ const allDevicesTypes = useMediaQueries(userDeviceState);
27
+ const { isMobile, isTablet, isDesktop, ...fullNamedDeviceTypes } = allDevicesTypes;
28
+ const deviceCurrentMainType = (isMobile && 'mobile') ||
29
+ (isTablet && 'tablet') ||
30
+ (isDesktop && 'desktop') ||
31
+ '';
32
+ const [deviceCurrentType, deviceTypesList] = useMemo(() => {
33
+ const deviceTypesList = Object.keys(allDevicesTypes).map((key) => camelCase(key.replace('is', '')));
34
+ // In same time "allDevicesTypes" can contain "isMobile" and "isMobileLarge" as true
35
+ let deviceCurrentType = Object.keys(fullNamedDeviceTypes).find(
36
+ // If "fullNamedDeviceTypes.isMobileLarge: true" - that our device
37
+ (key) => fullNamedDeviceTypes[key]);
38
+ // Or set main type (e.g. "isMobile")
39
+ if (!deviceCurrentType) {
40
+ deviceCurrentType = deviceCurrentMainType;
41
+ }
42
+ deviceCurrentType = camelCase(deviceCurrentType.replace('is', ''));
43
+ // On server side render we doesn't known user device and we need to set special word
44
+ return [deviceCurrentType || '_none_', deviceTypesList];
45
+ }, [allDevicesTypes, deviceCurrentMainType, fullNamedDeviceTypes]);
46
+ const deviceContextState = useMemo(() => {
47
+ return {
48
+ ...allDevicesTypes,
49
+ deviceCurrentMainType: deviceCurrentMainType,
50
+ deviceCurrentType: deviceCurrentType,
51
+ deviceTypesList: deviceTypesList,
52
+ };
53
+ }, [
54
+ allDevicesTypes,
55
+ deviceCurrentMainType,
56
+ deviceCurrentType,
57
+ deviceTypesList,
58
+ ]);
59
+ useEffect(() => {
60
+ setViewportProperty();
61
+ window.addEventListener('resize', setViewportProperty);
62
+ }, []);
63
+ return (jsx(UserDeviceContext.Provider, { value: deviceContextState, children: children }));
64
+ });
65
+ function useUserDeviceContext() {
66
+ const context = useContext(UserDeviceContext);
67
+ if (!context) {
68
+ throw new Error('useUserDeviceContext is not defined');
69
+ }
70
+ return context;
71
+ }
72
+
73
+ export { UIProvider, useUserDeviceContext };
@@ -1 +1,14 @@
1
- import{jsx as r}from"react/jsx-runtime";import{createContext as t,useMemo as e}from"react";const i=t({assetPrefix:void 0,ignorePathsList:void 0});function s(t){const{assetPrefix:s,ignorePathsList:o,children:n}=t,a=e(()=>({assetPrefix:s,ignorePathsList:o}),[s,o]);return r(i.Provider,{value:a,children:n})}export{i as UrlAssetPrefixContext,s as UrlAssetPrefixProvider};
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { createContext, useMemo } from 'react';
3
+
4
+ const UrlAssetPrefixContext = createContext({
5
+ assetPrefix: undefined,
6
+ ignorePathsList: undefined,
7
+ });
8
+ function UrlAssetPrefixProvider(props) {
9
+ const { assetPrefix, ignorePathsList, children } = props;
10
+ const value = useMemo(() => ({ assetPrefix, ignorePathsList }), [assetPrefix, ignorePathsList]);
11
+ return (jsx(UrlAssetPrefixContext.Provider, { value: value, children: children }));
12
+ }
13
+
14
+ export { UrlAssetPrefixContext, UrlAssetPrefixProvider };
@@ -1 +1,11 @@
1
- export{NotificationsProvider,statusToAppearanceList,useNotifications,useNotificationsAPI}from"./Notifications.js";export{UIProvider,useUserDeviceContext}from"./UIContext.js";export{UrlAssetPrefixContext,UrlAssetPrefixProvider}from"./UrlAssetPrefix.js";import"react/jsx-runtime";import"react";import"uuid";import"@itcase/common";import"lodash/camelCase";import"../hooks/useMediaQueries/useMediaQueries.js";import"react-responsive";import"../utils/setViewportProperty.js";
1
+ export { NotificationsProvider, statusToAppearanceList, useNotifications, useNotificationsAPI } from './Notifications.js';
2
+ export { UIProvider, useUserDeviceContext } from './UIContext.js';
3
+ export { UrlAssetPrefixContext, UrlAssetPrefixProvider } from './UrlAssetPrefix.js';
4
+ import 'react/jsx-runtime';
5
+ import 'react';
6
+ import 'uuid';
7
+ import '@itcase/common';
8
+ import 'lodash/camelCase';
9
+ import '../hooks/useMediaQueries/useMediaQueries.js';
10
+ import 'react-responsive';
11
+ import '../utils/setViewportProperty.js';
package/dist/hoc/index.js CHANGED
@@ -1 +1,5 @@
1
- export{urlWithAssetPrefix}from"./urlWithAssetPrefix.js";import"react/jsx-runtime";import"react";import"@itcase/common";import"../context/UrlAssetPrefix.js";
1
+ export { urlWithAssetPrefix } from './urlWithAssetPrefix.js';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
4
+ import '@itcase/common';
5
+ import '../context/UrlAssetPrefix.js';
@@ -1 +1,76 @@
1
- import{jsx as t}from"react/jsx-runtime";import r,{useContext as e}from"react";import{formatURL as s}from"@itcase/common";import{UrlAssetPrefixContext as i}from"../context/UrlAssetPrefix.js";const o=["src","imageSrc","svgSrc","placeholderUrl"],f=(f,...a)=>r.forwardRef(function(r,a){const{assetPrefix:c,ignorePathsList:m}=e(i),h=o.reduce((t,e)=>{let i=r[e];if(i&&"string"==typeof i){if(c){if(n(i,c,m)){i=`${s(c).slice(0,-1)}${i}`}}t[e]=i}return t},{});return t(f,{...r,...h,ref:a})}),n=(t,r,e=[])=>{if(t.startsWith("http:")||t.startsWith("https:")||t.startsWith("data:")||t.startsWith("blob:")||t.startsWith(r))return!1;for(const r of e)if(r instanceof RegExp){if(r.test(t))return!1}else if(s(t).startsWith(s(r)))return!1;return!0};export{f as urlWithAssetPrefix};
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React, { useContext } from 'react';
3
+ import { formatURL } from '@itcase/common';
4
+ import { UrlAssetPrefixContext } from '../context/UrlAssetPrefix.js';
5
+
6
+ const urlPropsList = ['src', 'imageSrc', 'svgSrc', 'placeholderUrl'];
7
+ /**
8
+ * HOC, который добавляет assetPrefix к URL-пропсам.
9
+ *
10
+ * @template P - Тип пропсов оборачиваемого компонента.
11
+ * @template T - Тип ref (если используется forwardRef).
12
+ * @template Check - Проверка на наличие хотя бы одного URL-пропа.
13
+ *
14
+ * @param WrappedComponent - Компонент, который оборачиваем.
15
+ * @param _error - Проверка: если ни одного URL-пропа нет, будет ошибка компиляции.
16
+ *
17
+ * @example
18
+ * const A = (props: { src?: string }) => <div />;
19
+ * urlWithAssetPrefix(A); // ✅ OK
20
+ *
21
+ * const B = (props: { id: string }) => <div />;
22
+ * urlWithAssetPrefix(B); // ❌ TS ошибка (нет url-пропов)
23
+ */
24
+ const urlWithAssetPrefix = (WrappedComponent, ..._error) => {
25
+ const HOC = React.forwardRef(function HOC(props, ref) {
26
+ const { assetPrefix, ignorePathsList } = useContext(UrlAssetPrefixContext);
27
+ const overrideProps = urlPropsList.reduce((resultProps, propKey) => {
28
+ let url = props[propKey];
29
+ if (url && typeof url === 'string') {
30
+ if (assetPrefix) {
31
+ const isNeedAssetPrefix = checkIsNeedAssetPrefix(url, assetPrefix, ignorePathsList);
32
+ if (isNeedAssetPrefix) {
33
+ const prefixPath = formatURL(assetPrefix).slice(0, -1);
34
+ url = `${prefixPath}${url}`;
35
+ }
36
+ }
37
+ resultProps[propKey] = url;
38
+ }
39
+ return resultProps;
40
+ }, {});
41
+ return jsx(WrappedComponent, { ...props, ...overrideProps, ref: ref });
42
+ });
43
+ return HOC;
44
+ };
45
+ const checkIsNeedAssetPrefix = (url, assetPrefix, ignorePathsList = []) => {
46
+ // Ignore prefix if:
47
+ const isPrefixIgnore =
48
+ // Url is absolute
49
+ url.startsWith('http:') ||
50
+ url.startsWith('https:') ||
51
+ // Url is data string
52
+ url.startsWith('data:') ||
53
+ url.startsWith('blob:') ||
54
+ // Url already have prefix
55
+ url.startsWith(assetPrefix);
56
+ if (isPrefixIgnore) {
57
+ return false;
58
+ }
59
+ // And check special paths for ignore prefix
60
+ for (const urlPath of ignorePathsList) {
61
+ if (urlPath instanceof RegExp) {
62
+ if (urlPath.test(url)) {
63
+ return false;
64
+ }
65
+ }
66
+ else {
67
+ if (formatURL(url).startsWith(formatURL(urlPath))) {
68
+ return false;
69
+ }
70
+ }
71
+ }
72
+ // Need to add prefix to url
73
+ return true;
74
+ };
75
+
76
+ export { urlWithAssetPrefix };
@@ -1 +1,24 @@
1
- export{useActiveClasses}from"./useActiveClasses/useActiveClasses.js";export{useAppearanceConfig}from"./useAppearanceConfig/useAppearanceConfig.js";export{useDevicePropsGenerator}from"./useDevicePropsGenerator/useDevicePropsGenerator.js";export{useDeviceTargetClass}from"./useDeviceTargetClass.js";export{useMediaQueries}from"./useMediaQueries/useMediaQueries.js";export{getStyleAttributeKey}from"./useStyles/styleAttributes.helpers.js";export{useStyles}from"./useStyles/useStyles.js";export{useViewportFix}from"./useViewportFix.js";import"clsx";import"./useActiveClasses/useActiveClasses.helpers.js";import"react";import"lodash/camelCase";import"lodash/castArray";import"lodash/upperFirst";import"../context/Notifications.js";import"react/jsx-runtime";import"uuid";import"@itcase/common";import"../context/UIContext.js";import"../utils/setViewportProperty.js";import"../context/UrlAssetPrefix.js";import"./useStyles/styleAttributes.js";import"lodash/maxBy";import"react-responsive";
1
+ export { useActiveClasses } from './useActiveClasses/useActiveClasses.js';
2
+ export { useAppearanceConfig } from './useAppearanceConfig/useAppearanceConfig.js';
3
+ export { useDevicePropsGenerator } from './useDevicePropsGenerator/useDevicePropsGenerator.js';
4
+ export { useDeviceTargetClass } from './useDeviceTargetClass.js';
5
+ export { useMediaQueries } from './useMediaQueries/useMediaQueries.js';
6
+ export { getStyleAttributeKey } from './useStyles/styleAttributes.helpers.js';
7
+ export { useStyles } from './useStyles/useStyles.js';
8
+ export { useViewportFix } from './useViewportFix.js';
9
+ import 'clsx';
10
+ import './useActiveClasses/useActiveClasses.helpers.js';
11
+ import 'react';
12
+ import 'lodash/camelCase';
13
+ import 'lodash/castArray';
14
+ import 'lodash/upperFirst';
15
+ import '../context/Notifications.js';
16
+ import 'react/jsx-runtime';
17
+ import 'uuid';
18
+ import '@itcase/common';
19
+ import '../context/UIContext.js';
20
+ import '../utils/setViewportProperty.js';
21
+ import '../context/UrlAssetPrefix.js';
22
+ import './useStyles/styleAttributes.js';
23
+ import 'lodash/maxBy';
24
+ import 'react-responsive';
@@ -1 +1,3 @@
1
- export{useActiveClasses}from"./useActiveClasses.js";import"clsx";import"./useActiveClasses.helpers.js";
1
+ export { useActiveClasses } from './useActiveClasses.js';
2
+ import 'clsx';
3
+ import './useActiveClasses.helpers.js';
@@ -1 +1,89 @@
1
- const e={fill:[{key:"fillClass",stateFn:({isActive:e,isDisabled:s})=>!e&&!s},{key:"fillHoverClass",stateFn:({isActive:e,isDisabled:s})=>!e&&!s},{key:"fillActiveClass",stateFn:({isActive:e,isDisabled:s})=>Boolean(e)&&!s},{key:"fillActiveHoverClass",stateFn:({isActive:e,isDisabled:s})=>Boolean(e)&&!s},{key:"fillDisabledClass",stateFn:({isActive:e,isDisabled:s})=>!e&&Boolean(s)}],borderColor:[{key:"borderColorClass",stateFn:({isActive:e,isDisabled:s})=>!e&&!s},{key:"borderColorHoverClass",stateFn:({isActive:e,isDisabled:s})=>!e&&!s},{key:"borderColorActiveClass",stateFn:({isActive:e,isDisabled:s})=>Boolean(e)&&!s}],textColor:[{key:"textColorClass",stateFn:({isActive:e,isDisabled:s})=>!e&&!s}]},s=e=>{const s=e.match(/(ActiveHover|Active|Hover|Disabled)/i);return s?"_"+s[0].replace(/ActiveHover/i,"active_hover").replace(/Active/i,"active").replace(/Hover/i,"hover").replace(/Disabled/i,"disabled").toLowerCase():""},i=e=>e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();export{e as CLASS_RULES,s as formatState,i as toKebabCase};
1
+ const CLASS_RULES = {
2
+ fill: [
3
+ {
4
+ key: 'fillClass',
5
+ stateFn: ({ isActive, isDisabled }) => !isActive && !isDisabled,
6
+ },
7
+ {
8
+ key: 'fillHoverClass',
9
+ stateFn: ({ isActive, isDisabled }) => !isActive && !isDisabled,
10
+ },
11
+ {
12
+ key: 'fillActiveClass',
13
+ stateFn: ({ isActive, isDisabled }) => Boolean(isActive) && !isDisabled,
14
+ },
15
+ {
16
+ key: 'fillActiveHoverClass',
17
+ stateFn: ({ isActive, isDisabled }) => Boolean(isActive) && !isDisabled,
18
+ },
19
+ {
20
+ key: 'fillDisabledClass',
21
+ stateFn: ({ isActive, isDisabled }) => !isActive && Boolean(isDisabled),
22
+ },
23
+ ],
24
+ borderColor: [
25
+ {
26
+ key: 'borderColorClass',
27
+ stateFn: ({ isActive, isDisabled }) => !isActive && !isDisabled,
28
+ },
29
+ {
30
+ key: 'borderColorHoverClass',
31
+ stateFn: ({ isActive, isDisabled }) => !isActive && !isDisabled,
32
+ },
33
+ {
34
+ key: 'borderColorActiveClass',
35
+ stateFn: ({ isActive, isDisabled }) => Boolean(isActive) && !isDisabled,
36
+ },
37
+ ],
38
+ textColor: [
39
+ {
40
+ key: 'textColorClass',
41
+ stateFn: ({ isActive, isDisabled }) => !isActive && !isDisabled,
42
+ },
43
+ ],
44
+ };
45
+ const formatState = (key) => {
46
+ // Try to find one of the state tokens in the input key:
47
+ // - matches "ActiveHover", "Active", "Hover" or "Disabled"
48
+ // - case-insensitive because of the /i flag
49
+ // Examples of matches:
50
+ // "fillActiveColorHover" -> match[0] === "ActiveHover"
51
+ // "borderDisabled" -> match[0] === "Disabled"
52
+ const stateMatch = key.match(/(ActiveHover|Active|Hover|Disabled)/i);
53
+ if (!stateMatch) {
54
+ return '';
55
+ }
56
+ // Replace the matched token with a normalized snake-like form and
57
+ // prepend an underscore. The chained replace calls map:
58
+ // ActiveHover -> active_hover
59
+ // Active -> active
60
+ // Hover -> hover
61
+ // Disabled -> disabled
62
+ // The final .toLowerCase() ensures output is lowercased regardless of input casing.
63
+ // Examples:
64
+ // "fillActiveColorHover" -> "_active_hover"
65
+ // "borderDisabled" -> "disabled"
66
+ return ('_' +
67
+ stateMatch[0]
68
+ .replace(/ActiveHover/i, 'active_hover')
69
+ .replace(/Active/i, 'active')
70
+ .replace(/Hover/i, 'hover')
71
+ .replace(/Disabled/i, 'disabled')
72
+ .toLowerCase());
73
+ };
74
+ // Insert a hyphen between a lowercase letter followed by an uppercase letter:
75
+ // - regex: /([a-z])([A-Z])/g
76
+ // ([a-z]) -> capture group 1: a lowercase letter
77
+ // ([A-Z]) -> capture group 2: an uppercase letter
78
+ // g -> global: replace all occurrences
79
+ // - replacement: '$1-$2' puts a hyphen between the two captured groups
80
+ // - finally .toLowerCase() to produce a full kebab-case string
81
+ //
82
+ // Examples:
83
+ // "myTestString" -> "my-test-string"
84
+ // "borderColorActiveHover" -> "border-color-active-hover"
85
+ const toKebabCase = (str) => {
86
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
87
+ };
88
+
89
+ export { CLASS_RULES, formatState, toKebabCase };
@@ -1 +1,63 @@
1
- const e=["Button","Checkbox","Radio","Checkmark","Avatar","AvatarStack","Badge","Breadcrumbs","Cell","Chips","Choice","Code","CookiesWarning","Dadata","DatePeriod","Divider","Dot","Drawer","Dropdown","DropdownItem","Flex","Grid","Group","HeroTitle","HTMLContent","Icon","Image","Input","InputPassword","Label","Link","List","Loader","Logo","MenuItem","Modal","ModalSheetBottom","Notification","Overlay","Pagination","RangeSlider","Response","ScrollBar","ScrollOnDrag","ScrollToView","Search","Segmented","Select","SvgContent","Swiper","Switch","Tab","Text","Textarea","Tile","Title","Tooltip","Video","Warning"];export{e as suffix};
1
+ const suffix = [
2
+ 'Button',
3
+ 'Checkbox',
4
+ 'Radio',
5
+ 'Checkmark',
6
+ 'Avatar',
7
+ 'AvatarStack',
8
+ 'Badge',
9
+ 'Breadcrumbs',
10
+ 'Cell',
11
+ 'Chips',
12
+ 'Choice',
13
+ 'Code',
14
+ 'CookiesWarning',
15
+ 'Dadata',
16
+ 'DatePeriod',
17
+ 'Divider',
18
+ 'Dot',
19
+ 'Drawer',
20
+ 'Dropdown',
21
+ 'DropdownItem',
22
+ 'Flex',
23
+ 'Grid',
24
+ 'Group',
25
+ 'HeroTitle',
26
+ 'HTMLContent',
27
+ 'Icon',
28
+ 'Image',
29
+ 'Input',
30
+ 'InputPassword',
31
+ 'Label',
32
+ 'Link',
33
+ 'List',
34
+ 'Loader',
35
+ 'Logo',
36
+ 'MenuItem',
37
+ 'Modal',
38
+ 'ModalSheetBottom',
39
+ 'Notification',
40
+ 'Overlay',
41
+ 'Pagination',
42
+ 'RangeSlider',
43
+ 'Response',
44
+ 'ScrollBar',
45
+ 'ScrollOnDrag',
46
+ 'ScrollToView',
47
+ 'Search',
48
+ 'Segmented',
49
+ 'Select',
50
+ 'SvgContent',
51
+ 'Swiper',
52
+ 'Switch',
53
+ 'Tab',
54
+ 'Text',
55
+ 'Textarea',
56
+ 'Tile',
57
+ 'Title',
58
+ 'Tooltip',
59
+ 'Video',
60
+ 'Warning',
61
+ ];
62
+
63
+ export { suffix };
@@ -1 +1,58 @@
1
- import e from"clsx";import{CLASS_RULES as s,toKebabCase as t,formatState as r}from"./useActiveClasses.helpers.js";const i=i=>{const{propsGenerator:o,suffixes:n=[],isActive:c,isDisabled:f}=i,a=[];Object.entries(s).forEach(([e,s])=>{const i=t(e);s.forEach(({key:e,stateFn:s})=>{const t=o[e];if(!t)return;if(s){if(!s({isActive:c,isDisabled:f}))return}const n=r(e);a.push(`${i}${n}_${t}`)})});return{rootClasses:e(a),suffixClasses:n.reduce((i,n)=>{const a=[];Object.entries(s).forEach(([e,s])=>{s.forEach(({key:s,stateFn:i})=>{const u=s.replace(e,""),l=e+n+u,p=o[l];if(!p)return;if(i){if(!i({isActive:c,isDisabled:f}))return}const h=r(l),C=t(e);a.push(`${C}${h}_${p}`)})});return i["HTMLContent"===n?"htmlContent":n[0].toLowerCase()+n.slice(1)]=e(a),i},{})}};export{i as useActiveClasses};
1
+ import clsx from 'clsx';
2
+ import { CLASS_RULES, toKebabCase, formatState } from './useActiveClasses.helpers.js';
3
+
4
+ const useActiveClasses = (params) => {
5
+ const { propsGenerator, suffixes = [], isActive, isDisabled } = params;
6
+ const rootClassesArray = [];
7
+ Object.entries(CLASS_RULES).forEach(([rulesName, rules]) => {
8
+ const kebabRuleName = toKebabCase(rulesName);
9
+ rules.forEach(({ key, stateFn }) => {
10
+ const value = propsGenerator[key];
11
+ if (!value) {
12
+ return;
13
+ }
14
+ if (stateFn) {
15
+ const active = stateFn({ isActive, isDisabled });
16
+ if (!active) {
17
+ return;
18
+ }
19
+ }
20
+ const stateName = formatState(key);
21
+ rootClassesArray.push(`${kebabRuleName}${stateName}_${value}`);
22
+ });
23
+ });
24
+ const rootClasses = clsx(rootClassesArray);
25
+ const suffixClasses = suffixes.reduce((acc, suffix) => {
26
+ const classes = [];
27
+ Object.entries(CLASS_RULES).forEach(([rulesName, rules]) => {
28
+ rules.forEach(({ key, stateFn }) => {
29
+ const withoutPrefixRulesName = key.replace(rulesName, '');
30
+ const propKey = rulesName + suffix + withoutPrefixRulesName;
31
+ const value = propsGenerator[propKey];
32
+ if (!value) {
33
+ return;
34
+ }
35
+ if (stateFn) {
36
+ const active = stateFn({ isActive, isDisabled });
37
+ if (!active) {
38
+ return;
39
+ }
40
+ }
41
+ const state = formatState(propKey);
42
+ const kebabName = toKebabCase(rulesName);
43
+ classes.push(`${kebabName}${state}_${value}`);
44
+ });
45
+ });
46
+ const suffixKey = suffix === 'HTMLContent'
47
+ ? 'htmlContent'
48
+ : (suffix[0].toLowerCase() + suffix.slice(1));
49
+ acc[suffixKey] = clsx(classes);
50
+ return acc;
51
+ }, {});
52
+ return {
53
+ rootClasses,
54
+ suffixClasses,
55
+ };
56
+ };
57
+
58
+ export { useActiveClasses };
@@ -1 +1,2 @@
1
- export{useAppearanceConfig}from"./useAppearanceConfig.js";import"react";
1
+ export { useAppearanceConfig } from './useAppearanceConfig.js';
2
+ import 'react';