@okshaun/components 0.3.2 → 0.3.3

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.
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
- import { forwardRef, useMemo, createElement, useEffect, createContext, useState, useContext, useRef } from "react";
2
+ import { forwardRef, useMemo, createElement, useEffect, useState, useRef, createContext, useContext, useSyncExternalStore } from "react";
3
3
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
4
+ import { b as breakpoints, c as containerSizes } from "./size.primitives-j2MFgtrT.js";
4
5
  function isObject(value) {
5
6
  return typeof value === "object" && value != null && !Array.isArray(value);
6
7
  }
@@ -97,10 +98,10 @@ function mapObject(obj, fn) {
97
98
  if (!isObject(obj)) return fn(obj);
98
99
  return walkObject(obj, (value) => fn(value));
99
100
  }
100
- function toResponsiveObject(values, breakpoints) {
101
+ function toResponsiveObject(values, breakpoints2) {
101
102
  return values.reduce(
102
103
  (acc, current, index) => {
103
- const key = breakpoints[index];
104
+ const key = breakpoints2[index];
104
105
  if (current != null) {
105
106
  acc[key] = current;
106
107
  }
@@ -2784,101 +2785,6 @@ const CheckboxInput = ({
2784
2785
  }
2785
2786
  );
2786
2787
  };
2787
- const THEME_STORAGE_KEY = "okshaun-theme-preference";
2788
- function getInitialTheme() {
2789
- const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
2790
- if (storedTheme) {
2791
- return storedTheme;
2792
- }
2793
- if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
2794
- return "dark";
2795
- }
2796
- return "light";
2797
- }
2798
- const ThemeContext = createContext(void 0);
2799
- function ThemeProvider({ children }) {
2800
- const [theme, setThemeState] = useState(() => getInitialTheme());
2801
- const setTheme = (newTheme) => {
2802
- setThemeState(newTheme);
2803
- localStorage.setItem(THEME_STORAGE_KEY, newTheme);
2804
- };
2805
- useEffect(() => {
2806
- document.documentElement.removeAttribute("data-color-mode");
2807
- document.documentElement.removeAttribute("data-theme");
2808
- document.documentElement.setAttribute("data-color-mode", theme);
2809
- }, [theme]);
2810
- useEffect(() => {
2811
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
2812
- const handleChange = (e) => {
2813
- const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
2814
- if (!storedTheme) {
2815
- setThemeState(e.matches ? "dark" : "light");
2816
- }
2817
- };
2818
- mediaQuery.addEventListener("change", handleChange);
2819
- return () => mediaQuery.removeEventListener("change", handleChange);
2820
- }, []);
2821
- return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme }, children });
2822
- }
2823
- function useTheme() {
2824
- const context2 = useContext(ThemeContext);
2825
- if (context2 === void 0) {
2826
- throw new Error("useTheme must be used within a ThemeProvider");
2827
- }
2828
- return context2;
2829
- }
2830
- const themeSwitchStyles = css({
2831
- position: "relative",
2832
- borderWidth: "2",
2833
- borderStyle: "solid",
2834
- borderColor: "border",
2835
- color: "transparent",
2836
- margin: "8",
2837
- borderRadius: "100",
2838
- cursor: "pointer",
2839
- display: "grid",
2840
- lineHeight: "none",
2841
- width: "14",
2842
- height: "14",
2843
- transition: "all",
2844
- "&:before": {
2845
- content: '""',
2846
- position: "absolute",
2847
- inset: "0",
2848
- opacity: 0,
2849
- display: "block",
2850
- borderRadius: "100",
2851
- bg: "bg.neutral.bold",
2852
- transition: "all",
2853
- transitionTimingFunction: "default",
2854
- transitionDuration: "normal"
2855
- },
2856
- _hover: {
2857
- cursor: "pointer",
2858
- bg: { base: "darkNeutral.0", _dark: "neutral.0" },
2859
- borderColor: "bg.neutral.bold",
2860
- "&:before": {
2861
- inset: "-8",
2862
- bg: { base: "darkNeutral.0", _dark: "neutral.0" },
2863
- opacity: 0.25
2864
- }
2865
- }
2866
- });
2867
- function ThemeSwitcher() {
2868
- const { theme, setTheme } = useTheme();
2869
- const toggleTheme = () => {
2870
- setTheme(theme === "light" ? "dark" : "light");
2871
- };
2872
- return /* @__PURE__ */ jsx(
2873
- "button",
2874
- {
2875
- className: themeSwitchStyles,
2876
- onClick: toggleTheme,
2877
- "aria-label": `Switch to ${theme === "light" ? "dark" : "light"} theme`,
2878
- children: /* @__PURE__ */ jsx("span", {})
2879
- }
2880
- );
2881
- }
2882
2788
  const Tooltip = ({
2883
2789
  trigger = "onHover",
2884
2790
  caret = true,
@@ -3230,14 +3136,240 @@ const Menu = ({ menuSection, iconPlacement, variant, multiSelectType, onChange }
3230
3136
  }) })
3231
3137
  ] });
3232
3138
  };
3139
+ const THEME_STORAGE_KEY = "okshaun-theme-preference";
3140
+ function getInitialTheme() {
3141
+ const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
3142
+ if (storedTheme) {
3143
+ return storedTheme;
3144
+ }
3145
+ if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
3146
+ return "dark";
3147
+ }
3148
+ return "light";
3149
+ }
3150
+ const ThemeContext = createContext(void 0);
3151
+ function ThemeProvider({ children }) {
3152
+ const [theme, setThemeState] = useState(() => getInitialTheme());
3153
+ const setTheme = (newTheme) => {
3154
+ setThemeState(newTheme);
3155
+ localStorage.setItem(THEME_STORAGE_KEY, newTheme);
3156
+ };
3157
+ useEffect(() => {
3158
+ document.documentElement.removeAttribute("data-color-mode");
3159
+ document.documentElement.removeAttribute("data-theme");
3160
+ document.documentElement.setAttribute("data-color-mode", theme);
3161
+ }, [theme]);
3162
+ useEffect(() => {
3163
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
3164
+ const handleChange = (e) => {
3165
+ const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
3166
+ if (!storedTheme) {
3167
+ setThemeState(e.matches ? "dark" : "light");
3168
+ }
3169
+ };
3170
+ mediaQuery.addEventListener("change", handleChange);
3171
+ return () => mediaQuery.removeEventListener("change", handleChange);
3172
+ }, []);
3173
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme }, children });
3174
+ }
3175
+ function useTheme() {
3176
+ const context2 = useContext(ThemeContext);
3177
+ if (context2 === void 0) {
3178
+ throw new Error("useTheme must be used within a ThemeProvider");
3179
+ }
3180
+ return context2;
3181
+ }
3182
+ const themeSwitchStyles = css({
3183
+ position: "relative",
3184
+ borderWidth: "2",
3185
+ borderStyle: "solid",
3186
+ borderColor: "border",
3187
+ color: "transparent",
3188
+ margin: "8",
3189
+ borderRadius: "100",
3190
+ cursor: "pointer",
3191
+ display: "grid",
3192
+ lineHeight: "none",
3193
+ width: "14",
3194
+ height: "14",
3195
+ transition: "all",
3196
+ "&:before": {
3197
+ content: '""',
3198
+ position: "absolute",
3199
+ inset: "0",
3200
+ opacity: 0,
3201
+ display: "block",
3202
+ borderRadius: "100",
3203
+ bg: "bg.neutral.bold",
3204
+ transition: "all",
3205
+ transitionTimingFunction: "default",
3206
+ transitionDuration: "normal"
3207
+ },
3208
+ _hover: {
3209
+ cursor: "pointer",
3210
+ bg: { base: "darkNeutral.0", _dark: "neutral.0" },
3211
+ borderColor: "bg.neutral.bold",
3212
+ "&:before": {
3213
+ inset: "-8",
3214
+ bg: { base: "darkNeutral.0", _dark: "neutral.0" },
3215
+ opacity: 0.25
3216
+ }
3217
+ }
3218
+ });
3219
+ function ThemeSwitcher() {
3220
+ const { theme, setTheme } = useTheme();
3221
+ const toggleTheme = () => {
3222
+ setTheme(theme === "light" ? "dark" : "light");
3223
+ };
3224
+ return /* @__PURE__ */ jsx(
3225
+ "button",
3226
+ {
3227
+ className: themeSwitchStyles,
3228
+ onClick: toggleTheme,
3229
+ "aria-label": `Switch to ${theme === "light" ? "dark" : "light"} theme`,
3230
+ children: /* @__PURE__ */ jsx("span", {})
3231
+ }
3232
+ );
3233
+ }
3234
+ function useMediaQuery(breakpoint, direction = "min") {
3235
+ const query = useMemo(() => {
3236
+ const breakpointValue = breakpoints[breakpoint];
3237
+ const breakpointNum = parseInt(breakpointValue, 10);
3238
+ return direction === "min" ? `(min-width: ${breakpointValue})` : `(max-width: ${breakpointNum - 1}px)`;
3239
+ }, [breakpoint, direction]);
3240
+ const mediaQuery = useMemo(() => {
3241
+ if (typeof window === "undefined") {
3242
+ return {
3243
+ matches: false,
3244
+ addEventListener: () => {
3245
+ },
3246
+ removeEventListener: () => {
3247
+ }
3248
+ };
3249
+ }
3250
+ return window.matchMedia(query);
3251
+ }, [query]);
3252
+ return useSyncExternalStore(
3253
+ (callback) => {
3254
+ mediaQuery.addEventListener("change", callback);
3255
+ return () => {
3256
+ mediaQuery.removeEventListener("change", callback);
3257
+ };
3258
+ },
3259
+ () => mediaQuery.matches,
3260
+ // SSR fallback - return false on server
3261
+ () => false
3262
+ );
3263
+ }
3264
+ function useContainerQuery(containerRef, size, direction = "min") {
3265
+ const query = useMemo(() => {
3266
+ const sizeValue = containerSizes[size].value;
3267
+ const sizeNum = parseFloat(sizeValue);
3268
+ return direction === "min" ? `(min-width: ${sizeValue})` : `(max-width: ${sizeNum - 0.0625}rem)`;
3269
+ }, [size, direction]);
3270
+ return useSyncExternalStore(
3271
+ (callback) => {
3272
+ if (typeof window === "undefined" || !containerRef.current) {
3273
+ return () => {
3274
+ };
3275
+ }
3276
+ const element = containerRef.current;
3277
+ const sizeValue = containerSizes[size].value;
3278
+ const sizeNum = parseFloat(sizeValue);
3279
+ const threshold = direction === "min" ? sizeNum : sizeNum - 0.0625;
3280
+ const checkSize = () => {
3281
+ if (!element) return false;
3282
+ const width = element.offsetWidth;
3283
+ const widthInRem = width / parseFloat(getComputedStyle(document.documentElement).fontSize);
3284
+ return direction === "min" ? widthInRem >= threshold : widthInRem < threshold;
3285
+ };
3286
+ if ("queryContainer" in element) {
3287
+ try {
3288
+ const containerQuery = element.queryContainer(query);
3289
+ containerQuery.addEventListener("change", callback);
3290
+ return () => {
3291
+ containerQuery.removeEventListener("change", callback);
3292
+ };
3293
+ } catch {
3294
+ }
3295
+ }
3296
+ let currentMatches = checkSize();
3297
+ const callbacks = /* @__PURE__ */ new Set();
3298
+ let observer = null;
3299
+ if (typeof ResizeObserver !== "undefined") {
3300
+ observer = new ResizeObserver(() => {
3301
+ const newMatches = checkSize();
3302
+ if (newMatches !== currentMatches) {
3303
+ currentMatches = newMatches;
3304
+ callbacks.forEach((cb) => cb());
3305
+ }
3306
+ });
3307
+ observer.observe(element);
3308
+ }
3309
+ callbacks.add(callback);
3310
+ return () => {
3311
+ callbacks.delete(callback);
3312
+ if (callbacks.size === 0 && observer) {
3313
+ observer.disconnect();
3314
+ }
3315
+ };
3316
+ },
3317
+ () => {
3318
+ if (typeof window === "undefined" || !containerRef.current) {
3319
+ return false;
3320
+ }
3321
+ const element = containerRef.current;
3322
+ const sizeValue = containerSizes[size].value;
3323
+ const sizeNum = parseFloat(sizeValue);
3324
+ const threshold = direction === "min" ? sizeNum : sizeNum - 0.0625;
3325
+ if ("queryContainer" in element) {
3326
+ try {
3327
+ const containerQuery = element.queryContainer(query);
3328
+ return containerQuery.matches;
3329
+ } catch {
3330
+ }
3331
+ }
3332
+ const width = element.offsetWidth;
3333
+ const widthInRem = width / parseFloat(getComputedStyle(document.documentElement).fontSize);
3334
+ return direction === "min" ? widthInRem >= threshold : widthInRem < threshold;
3335
+ },
3336
+ // SSR fallback - return false on server
3337
+ () => false
3338
+ );
3339
+ }
3340
+ function BreakpointIndicator() {
3341
+ const isXs = useMediaQuery("xs");
3342
+ const isSm = useMediaQuery("sm");
3343
+ const isMd = useMediaQuery("md");
3344
+ const isLg = useMediaQuery("lg");
3345
+ const isXl = useMediaQuery("xl");
3346
+ const is2Xl = useMediaQuery("2xl");
3347
+ let breakpoint = /* @__PURE__ */ jsx(Tag, { hue: "red", appearance: "bold", children: "@media/base" });
3348
+ if (is2Xl) {
3349
+ breakpoint = /* @__PURE__ */ jsx(Tag, { hue: "blue", appearance: "bold", children: "@media/2xl" });
3350
+ } else if (isXl) {
3351
+ breakpoint = /* @__PURE__ */ jsx(Tag, { hue: "teal", appearance: "bold", children: "@media/xl" });
3352
+ } else if (isLg) {
3353
+ breakpoint = /* @__PURE__ */ jsx(Tag, { hue: "green", appearance: "bold", children: "@media/lg" });
3354
+ } else if (isMd) {
3355
+ breakpoint = /* @__PURE__ */ jsx(Tag, { hue: "lime", appearance: "bold", children: "@media/md" });
3356
+ } else if (isSm) {
3357
+ breakpoint = /* @__PURE__ */ jsx(Tag, { hue: "yellow", appearance: "bold", children: "@media/sm" });
3358
+ } else if (isXs) {
3359
+ breakpoint = /* @__PURE__ */ jsx(Tag, { hue: "orange", appearance: "bold", children: "@media/xs" });
3360
+ }
3361
+ return breakpoint;
3362
+ }
3233
3363
  export {
3234
3364
  Badge,
3235
3365
  Box,
3236
3366
  Breadcrumbs,
3367
+ BreakpointIndicator,
3237
3368
  Button,
3238
3369
  Card,
3239
3370
  Checkbox,
3240
3371
  CheckboxInput,
3372
+ Code,
3241
3373
  Divider,
3242
3374
  Heading,
3243
3375
  Icon,
@@ -3260,6 +3392,8 @@ export {
3260
3392
  ToggleInput,
3261
3393
  Tooltip,
3262
3394
  splitProps,
3395
+ useContainerQuery,
3396
+ useMediaQuery,
3263
3397
  useTheme
3264
3398
  };
3265
3399
  //# sourceMappingURL=index.js.map