@stfrigerio/sito-template 0.1.6 → 0.1.8

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.
@@ -1,5 +1,9 @@
1
1
  import React from 'react';
2
- export type SearchFilter = 'all' | 'projects' | 'clients' | 'contacts' | 'interactions' | 'team';
2
+ export interface FilterOption {
3
+ value: string;
4
+ label: string;
5
+ icon: React.ElementType;
6
+ }
3
7
  export interface SearchResult {
4
8
  id: string;
5
9
  type: string;
@@ -10,13 +14,18 @@ export interface SearchResult {
10
14
  export interface SearchBarProps {
11
15
  className?: string;
12
16
  placeholder?: string;
13
- onSearch?: (query: string, filter: SearchFilter) => Promise<SearchResult[]>;
17
+ onSearch?: (query: string, filter: string) => Promise<SearchResult[]>;
14
18
  onResultClick?: (result: SearchResult) => void;
15
19
  onClear?: () => void;
16
20
  debounceDelay?: number;
17
21
  minSearchLength?: number;
18
22
  showFilter?: boolean;
19
23
  enableKeyboardShortcut?: boolean;
24
+ filterOptions?: FilterOption[];
25
+ entityIcons?: {
26
+ [key: string]: React.ElementType;
27
+ };
20
28
  }
29
+ export type SearchFilter = 'all' | 'projects' | 'clients' | 'contacts' | 'interactions' | 'team';
21
30
  export declare const SearchBar: React.FC<SearchBarProps>;
22
31
  //# sourceMappingURL=SearchBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/SearchBar/SearchBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,cAAc,GAAG,MAAM,CAAC;AAEjG,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC5E,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC;AAmBD,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAkV9C,CAAC"}
1
+ {"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/SearchBar/SearchBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACtE,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,WAAW,CAAA;KAAE,CAAC;CACtD;AAqBD,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,cAAc,GAAG,MAAM,CAAC;AAEjG,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAuV9C,CAAC"}
@@ -1,3 +1,3 @@
1
1
  export { SearchBar } from './SearchBar';
2
- export type { SearchBarProps, SearchResult, SearchFilter } from './SearchBar';
2
+ export type { SearchBarProps, SearchResult, SearchFilter, FilterOption } from './SearchBar';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/SearchBar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/SearchBar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -1,9 +1,15 @@
1
1
  import React from 'react';
2
- export type TabType = 'details' | 'github' | 'jira' | 'functional';
3
- interface TabsProps {
4
- activeTab: TabType;
5
- onTabChange: (tab: TabType) => void;
2
+ export interface Tab {
3
+ id: string;
4
+ label: string;
5
+ icon?: React.ComponentType<any> | React.ReactNode;
6
+ }
7
+ export interface TabsProps {
8
+ activeTab: string;
9
+ onTabChange: (tab: string) => void;
10
+ tabs?: Tab[];
11
+ className?: string;
6
12
  }
13
+ export type TabType = 'details' | 'github' | 'jira' | 'functional';
7
14
  export declare const Tabs: React.FC<TabsProps>;
8
- export {};
9
15
  //# sourceMappingURL=Tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/Tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAC;AAEnE,UAAU,SAAS;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC;AASD,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAkCpC,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/Tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,WAAW,GAAG;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;CACrD;AAED,MAAM,WAAW,SAAS;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAC;AAEnE,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAgDpC,CAAC"}
@@ -1,9 +1,16 @@
1
1
  import React from 'react';
2
- interface ThemeSwitcherProps {
2
+ export interface ThemeOption {
3
+ value: string;
4
+ label: string;
5
+ icon: React.ReactNode;
6
+ }
7
+ export interface ThemeSwitcherProps {
3
8
  variant?: 'button' | 'dropdown' | 'toggle';
4
9
  showLabel?: boolean;
5
10
  className?: string;
11
+ currentTheme?: string;
12
+ onThemeChange?: (theme: string) => void;
13
+ themes?: ThemeOption[];
6
14
  }
7
15
  export declare const ThemeSwitcher: React.FC<ThemeSwitcherProps>;
8
- export {};
9
16
  //# sourceMappingURL=ThemeSwitcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeSwitcher.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/ThemeSwitcher/ThemeSwitcher.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,UAAU,kBAAkB;IACxB,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC3C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAuGtD,CAAC"}
1
+ {"version":3,"file":"ThemeSwitcher.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/ThemeSwitcher/ThemeSwitcher.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC3C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsHtD,CAAC"}
@@ -1,10 +1,11 @@
1
1
  export { EditFAB } from './EditFAB';
2
2
  export type { EditFABProps } from './EditFAB';
3
3
  export { SearchBar } from './SearchBar';
4
- export type { SearchBarProps } from './SearchBar';
4
+ export type { SearchBarProps, FilterOption, SearchResult, SearchFilter } from './SearchBar';
5
5
  export { TimeInput } from './TimeInput';
6
6
  export type { TimeInputProps } from './TimeInput';
7
7
  export { ThemeSwitcher } from './ThemeSwitcher/ThemeSwitcher';
8
+ export type { ThemeSwitcherProps, ThemeOption } from './ThemeSwitcher/ThemeSwitcher';
8
9
  export { Tabs } from './Tabs/Tabs';
9
- export type { TabType } from './Tabs/Tabs';
10
+ export type { TabsProps, Tab } from './Tabs/Tabs';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/molecules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/molecules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5F,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAErF,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC"}
@@ -10,6 +10,8 @@ interface PieChartProps {
10
10
  height?: number;
11
11
  title?: string;
12
12
  showLegend?: boolean;
13
+ unit?: string;
14
+ centerLabel?: string;
13
15
  }
14
16
  export declare const PieChart: React.FC<PieChartProps>;
15
17
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"PieChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/PieChart/PieChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAIhD,UAAU,YAAY;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,UAAU,aAAa;IACnB,IAAI,EAAE,YAAY,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB;AASD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAqI5C,CAAA"}
1
+ {"version":3,"file":"PieChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/PieChart/PieChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAIhD,UAAU,YAAY;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,UAAU,aAAa;IACnB,IAAI,EAAE,YAAY,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAsBD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAoL5C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"QuantifiableHabitsChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/QuantifiableHabitsChart/QuantifiableHabitsChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAA;AAInE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAA;AAOnE,UAAU,SAAS;IACf,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,CAAA;CACvC;AAED,UAAU,4BAA4B;IAClC,IAAI,EAAE,SAAS,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,QAAQ,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;IAC9D,WAAW,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACvC,WAAW,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CAC1C;AAcD,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,4BAA4B,CAuU1E,CAAA"}
1
+ {"version":3,"file":"QuantifiableHabitsChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/QuantifiableHabitsChart/QuantifiableHabitsChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAA;AAInE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAA;AAOnE,UAAU,SAAS;IACf,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,CAAA;CACvC;AAED,UAAU,4BAA4B;IAClC,IAAI,EAAE,SAAS,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,QAAQ,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;IAC9D,WAAW,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACvC,WAAW,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CAC1C;AAcD,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,4BAA4B,CA8T1E,CAAA"}
@@ -10,6 +10,8 @@ interface SunburstChartProps {
10
10
  height?: number;
11
11
  title?: string;
12
12
  tagColors?: Record<string, string>;
13
+ unit?: string;
14
+ centerLabel?: string;
13
15
  }
14
16
  export declare const SunburstChart: React.FC<SunburstChartProps>;
15
17
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"SunburstChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/SunburstChart/SunburstChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAA;AAIzD,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B;AAED,UAAU,kBAAkB;IACxB,IAAI,EAAE,cAAc,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACrC;AAQD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAwJtD,CAAA"}
1
+ {"version":3,"file":"SunburstChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/SunburstChart/SunburstChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAA;AAIzD,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B;AAED,UAAU,kBAAkB;IACxB,IAAI,EAAE,cAAc,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAqBD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAwNtD,CAAA"}
package/dist/index.esm.js CHANGED
@@ -1178,7 +1178,8 @@ const EditFAB = ({ canEdit, isEditMode, hasUnsavedChanges = false, isSaving = fa
1178
1178
 
1179
1179
  var styles$a = {"searchContainer":"SearchBar-module_searchContainer__TdM1w","searchInputWrapper":"SearchBar-module_searchInputWrapper__kCZLU","searchIcon":"SearchBar-module_searchIcon__IIxEu","searchInput":"SearchBar-module_searchInput__V4gkE","clearButton":"SearchBar-module_clearButton__7fNIY","filterSelect":"SearchBar-module_filterSelect__xIVE4","resultsDropdown":"SearchBar-module_resultsDropdown__yh6NF","loadingState":"SearchBar-module_loadingState__4gidK","emptyState":"SearchBar-module_emptyState__RbI4s","spinner":"SearchBar-module_spinner__PMc6-","resultsGroups":"SearchBar-module_resultsGroups__U24DC","resultGroup":"SearchBar-module_resultGroup__SoTQH","groupHeader":"SearchBar-module_groupHeader__bFRHA","groupIcon":"SearchBar-module_groupIcon__9ENM-","groupTitle":"SearchBar-module_groupTitle__ZekZs","groupCount":"SearchBar-module_groupCount__PQIqw","groupResults":"SearchBar-module_groupResults__xTF52","resultItem":"SearchBar-module_resultItem__VaKKy","highlighted":"SearchBar-module_highlighted__Q-3sH","resultTitle":"SearchBar-module_resultTitle__i1uqL","resultSubtitle":"SearchBar-module_resultSubtitle__LQOJ1","resultMeta":"SearchBar-module_resultMeta__Kmkrn","resultContent":"SearchBar-module_resultContent__TzVzL","highlight":"SearchBar-module_highlight__Q3PSP"};
1180
1180
 
1181
- const filterOptions = [
1181
+ // Default filter options for backwards compatibility
1182
+ const defaultFilterOptions = [
1182
1183
  { value: 'all', label: 'All', icon: FiSearch },
1183
1184
  { value: 'projects', label: 'Projects', icon: FiFolder },
1184
1185
  { value: 'clients', label: 'Clients', icon: FiUsers },
@@ -1186,16 +1187,18 @@ const filterOptions = [
1186
1187
  { value: 'interactions', label: 'Interactions', icon: FiMessageSquare },
1187
1188
  { value: 'team', label: 'Team', icon: FiUserPlus },
1188
1189
  ];
1189
- const entityIcons = {
1190
+ const defaultEntityIcons = {
1190
1191
  projects: FiFolder,
1191
1192
  clients: FiUsers,
1192
1193
  contacts: FiBook,
1193
1194
  interactions: FiMessageSquare,
1194
1195
  team: FiUserPlus,
1195
1196
  };
1196
- const SearchBar = ({ className, placeholder = "Search (Ctrl+Space)...", onSearch, onResultClick, onClear, debounceDelay = 300, minSearchLength = 2, showFilter = true, enableKeyboardShortcut = true }) => {
1197
+ const SearchBar = ({ className, placeholder = "Search (Ctrl+Space)...", onSearch, onResultClick, onClear, debounceDelay = 300, minSearchLength = 2, showFilter = true, enableKeyboardShortcut = true, filterOptions: customFilterOptions, entityIcons: customEntityIcons }) => {
1198
+ const filterOptions = customFilterOptions ?? defaultFilterOptions;
1199
+ const entityIcons = customEntityIcons ?? defaultEntityIcons;
1197
1200
  const [query, setQuery] = useState('');
1198
- const [filter, setFilter] = useState('all');
1201
+ const [filter, setFilter] = useState(filterOptions[0]?.value ?? 'all');
1199
1202
  const [results, setResults] = useState([]);
1200
1203
  const [isLoading, setIsLoading] = useState(false);
1201
1204
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
@@ -1479,9 +1482,19 @@ const useTheme = () => {
1479
1482
 
1480
1483
  var styles$7 = {"button":"ThemeSwitcher-module_button__VfRjU","iconWrapper":"ThemeSwitcher-module_iconWrapper__FpHo8","label":"ThemeSwitcher-module_label__2Hfkp","toggle":"ThemeSwitcher-module_toggle__ATXx4","toggleTrack":"ThemeSwitcher-module_toggleTrack__x28Rv","toggleThumb":"ThemeSwitcher-module_toggleThumb__V8QeN","dropdown":"ThemeSwitcher-module_dropdown__3qLdt","dropdownTrigger":"ThemeSwitcher-module_dropdownTrigger__UzYV5","dropdownMenu":"ThemeSwitcher-module_dropdownMenu__3L5hT","dropdownItem":"ThemeSwitcher-module_dropdownItem__inw-K","active":"ThemeSwitcher-module_active__OHP19","icon":"ThemeSwitcher-module_icon__iRZiJ","text":"ThemeSwitcher-module_text__OCOoA"};
1481
1484
 
1482
- const ThemeSwitcher = ({ variant = 'button', showLabel = false, className = '', }) => {
1483
- const { theme, setTheme } = useTheme();
1484
- const themes = [
1485
+ const ThemeSwitcher = ({ variant = 'button', showLabel = false, className = '', currentTheme, onThemeChange, themes: customThemes, }) => {
1486
+ // Try to use internal context if available, otherwise use props
1487
+ const contextTheme = (() => {
1488
+ try {
1489
+ return useTheme();
1490
+ }
1491
+ catch {
1492
+ return null;
1493
+ }
1494
+ })();
1495
+ const theme = currentTheme ?? contextTheme?.theme ?? 'light';
1496
+ const setTheme = onThemeChange ?? contextTheme?.setTheme ?? (() => { });
1497
+ const defaultThemes = [
1485
1498
  { value: 'light', label: 'Light', icon: jsx(FiSun, {}) },
1486
1499
  { value: 'dark', label: 'Dark', icon: jsx(FiMoon, {}) },
1487
1500
  { value: 'lossito', label: 'Lossito Light', icon: '✨' },
@@ -1489,21 +1502,22 @@ const ThemeSwitcher = ({ variant = 'button', showLabel = false, className = '',
1489
1502
  { value: 'dmood', label: 'Dmood Light', icon: '💙' },
1490
1503
  { value: 'dmood-dark', label: 'Dmood Dark', icon: '🌌' },
1491
1504
  ];
1505
+ const themes = customThemes ?? defaultThemes;
1492
1506
  const currentThemeIndex = themes.findIndex(t => t.value === theme);
1493
- const currentTheme = themes[currentThemeIndex];
1507
+ const currentThemeData = themes[currentThemeIndex] ?? themes[0];
1494
1508
  if (variant === 'toggle') {
1495
1509
  // Simple toggle between light and dark
1496
1510
  const isDark = theme.includes('dark');
1497
1511
  return (jsxs(motion.button, { className: `${styles$7.toggle} ${className}`, onClick: () => setTheme(isDark ? 'light' : 'dark'), whileTap: { scale: 0.95 }, "aria-label": "Toggle theme", children: [jsx(motion.div, { className: styles$7.toggleTrack, animate: { backgroundColor: isDark ? 'var(--color-primary)' : 'var(--color-border)' }, children: jsx(motion.div, { className: styles$7.toggleThumb, animate: { x: isDark ? 24 : 0 }, transition: { type: 'spring', stiffness: 500, damping: 30 }, children: isDark ? jsx(FiMoon, { size: 14 }) : jsx(FiSun, { size: 14 }) }) }), showLabel && jsx("span", { className: styles$7.label, children: isDark ? 'Dark' : 'Light' })] }));
1498
1512
  }
1499
1513
  if (variant === 'dropdown') {
1500
- return (jsxs("div", { className: `${styles$7.dropdown} ${className}`, children: [jsxs(motion.button, { className: styles$7.dropdownTrigger, whileTap: { scale: 0.98 }, children: [currentTheme.icon, showLabel && jsx("span", { className: styles$7.label, children: currentTheme.label })] }), jsx(motion.div, { className: styles$7.dropdownMenu, initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, children: themes.map((t) => (jsxs(motion.button, { className: `${styles$7.dropdownItem} ${theme === t.value ? styles$7.active : ''}`, onClick: () => setTheme(t.value), whileHover: { x: 4 }, whileTap: { scale: 0.98 }, children: [jsx("span", { className: styles$7.icon, children: t.icon }), jsx("span", { className: styles$7.text, children: t.label })] }, t.value))) })] }));
1514
+ return (jsxs("div", { className: `${styles$7.dropdown} ${className}`, children: [jsxs(motion.button, { className: styles$7.dropdownTrigger, whileTap: { scale: 0.98 }, children: [currentThemeData.icon, showLabel && jsx("span", { className: styles$7.label, children: currentThemeData.label })] }), jsx(motion.div, { className: styles$7.dropdownMenu, initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, children: themes.map((t) => (jsxs(motion.button, { className: `${styles$7.dropdownItem} ${theme === t.value ? styles$7.active : ''}`, onClick: () => setTheme(t.value), whileHover: { x: 4 }, whileTap: { scale: 0.98 }, children: [jsx("span", { className: styles$7.icon, children: t.icon }), jsx("span", { className: styles$7.text, children: t.label })] }, t.value))) })] }));
1501
1515
  }
1502
1516
  // Default button variant - cycles through themes
1503
1517
  return (jsxs(motion.button, { className: `${styles$7.button} ${className}`, onClick: () => {
1504
1518
  const nextIndex = (currentThemeIndex + 1) % themes.length;
1505
1519
  setTheme(themes[nextIndex].value);
1506
- }, whileTap: { scale: 0.95 }, whileHover: { scale: 1.05 }, "aria-label": `Current theme: ${currentTheme.label}. Click to change.`, children: [jsx(motion.div, { initial: { rotate: -180, opacity: 0 }, animate: { rotate: 0, opacity: 1 }, exit: { rotate: 180, opacity: 0 }, transition: { duration: 0.3 }, className: styles$7.iconWrapper, children: currentTheme.icon }, theme), showLabel && jsx("span", { className: styles$7.label, children: currentTheme.label })] }));
1520
+ }, whileTap: { scale: 0.95 }, whileHover: { scale: 1.05 }, "aria-label": `Current theme: ${currentThemeData.label}. Click to change.`, children: [jsx(motion.div, { initial: { rotate: -180, opacity: 0 }, animate: { rotate: 0, opacity: 1 }, exit: { rotate: 180, opacity: 0 }, transition: { duration: 0.3 }, className: styles$7.iconWrapper, children: currentThemeData.icon }, theme), showLabel && jsx("span", { className: styles$7.label, children: currentThemeData.label })] }));
1507
1521
  };
1508
1522
 
1509
1523
  // THIS FILE IS AUTO GENERATED
@@ -1513,15 +1527,16 @@ function SiJira (props) {
1513
1527
 
1514
1528
  var styles$6 = {"tabs":"Tabs-module_tabs__Vlvn7","tab":"Tabs-module_tab__uQKim","tabIcon":"Tabs-module_tabIcon__AgN-O"};
1515
1529
 
1516
- const tabs = [
1530
+ // Default tabs for backwards compatibility
1531
+ const defaultTabs = [
1517
1532
  { id: 'details', icon: FiInfo, label: 'Dettagli' },
1518
1533
  { id: 'github', icon: FiGithub, label: 'GitHub' },
1519
1534
  { id: 'jira', icon: SiJira, label: 'Jira' },
1520
1535
  { id: 'functional', icon: FiInfo, label: 'Analisi funzionale' }
1521
1536
  ];
1522
- const Tabs = ({ activeTab, onTabChange }) => {
1523
- return (jsx("div", { className: styles$6.tabs, children: tabs.map((tab) => {
1524
- const Icon = tab.icon;
1537
+ const Tabs = ({ activeTab, onTabChange, tabs: customTabs, className = '' }) => {
1538
+ const tabs = customTabs ?? defaultTabs;
1539
+ return (jsx("div", { className: `${styles$6.tabs} ${className}`, children: tabs.map((tab) => {
1525
1540
  const isActive = activeTab === tab.id;
1526
1541
  return (jsxs(motion.button, { className: styles$6.tab, "data-active": isActive, onClick: () => onTabChange(tab.id), style: { position: 'relative' }, children: [jsx(motion.div, { animate: {
1527
1542
  rotate: isActive ? [0, -10, 10, -5, 5, 0] : 0,
@@ -1530,7 +1545,7 @@ const Tabs = ({ activeTab, onTabChange }) => {
1530
1545
  duration: 0.5,
1531
1546
  ease: 'easeInOut'
1532
1547
  }
1533
- }, children: jsx(Icon, { className: styles$6.tabIcon }) }), jsx("span", { children: tab.label })] }, tab.id));
1548
+ }, children: tab.icon && (typeof tab.icon === 'function' ? (jsx("span", { className: styles$6.tabIcon, children: React.createElement(tab.icon) })) : (jsx("span", { className: styles$6.tabIcon, children: tab.icon }))) }), jsx("span", { children: tab.label })] }, tab.id));
1534
1549
  }) }));
1535
1550
  };
1536
1551
 
@@ -2214,11 +2229,22 @@ const BooleansHeatmap = ({ data, habitName, width = 800, height = 200, habitColo
2214
2229
  var styles$1 = {"container":"SunburstChart-module_container__w1ZYc","title":"SunburstChart-module_title__T6Ak7","chart":"SunburstChart-module_chart__BFM6E","tooltip":"SunburstChart-module_tooltip__TuTAN"};
2215
2230
 
2216
2231
  const COLOR_PALETTE = [
2217
- '#d4af37', '#FFD700', '#FFA500', '#FF8C00',
2218
- '#FF6347', '#DC143C', '#8B4513', '#A0522D',
2219
- '#DEB887', '#F4A460', '#D2691E', '#CD853F'
2232
+ '#6366f1', '#8b5cf6', '#06b6d4', '#10b981',
2233
+ '#f59e0b', '#ef4444', '#ec4899', '#84cc16',
2234
+ '#f97316', '#3b82f6', '#14b8a6', '#f59e0b'
2220
2235
  ];
2221
- const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Chart', tagColors = {} }) => {
2236
+ // Calculate text color based on background luminance for optimal contrast
2237
+ const getTextColor$1 = (backgroundColor) => {
2238
+ const color = d3.color(backgroundColor);
2239
+ if (!color)
2240
+ return '#ffffff';
2241
+ const rgb = color.rgb();
2242
+ // Calculate relative luminance using WCAG formula
2243
+ const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
2244
+ // Return white text for dark backgrounds, black for light backgrounds
2245
+ return luminance > 0.5 ? '#000000' : '#ffffff';
2246
+ };
2247
+ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Chart', tagColors = {}, unit = 'items', centerLabel }) => {
2222
2248
  const svgRef = useRef(null);
2223
2249
  const colorMap = useRef(new Map()).current;
2224
2250
  const colorIndex = useRef(0);
@@ -2261,7 +2287,8 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2261
2287
  .startAngle(d => d.x0)
2262
2288
  .endAngle(d => d.x1)
2263
2289
  .innerRadius(d => Math.sqrt(d.y0))
2264
- .outerRadius(d => Math.sqrt(d.y1));
2290
+ .outerRadius(d => Math.sqrt(d.y1))
2291
+ .cornerRadius(3);
2265
2292
  const tooltip = d3.select('body').append('div')
2266
2293
  .attr('class', styles$1.tooltip)
2267
2294
  .style('opacity', 0)
@@ -2280,11 +2307,20 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2280
2307
  .attr('stroke', 'var(--bg-primary)')
2281
2308
  .attr('stroke-width', 2)
2282
2309
  .style('cursor', 'pointer')
2310
+ .style('filter', 'drop-shadow(0 1px 3px rgba(0,0,0,0.12))')
2283
2311
  .on('mouseover', function (event, d) {
2312
+ const hoverArc = d3.arc()
2313
+ .startAngle(d => d.x0)
2314
+ .endAngle(d => d.x1)
2315
+ .innerRadius(d => Math.sqrt(d.y0) - 2)
2316
+ .outerRadius(d => Math.sqrt(d.y1) + 4)
2317
+ .cornerRadius(3);
2284
2318
  d3.select(this)
2285
2319
  .transition()
2286
- .duration(200)
2287
- .style('opacity', 0.8);
2320
+ .duration(150)
2321
+ .attr('d', d => hoverArc(d))
2322
+ .style('filter', 'drop-shadow(0 2px 8px rgba(0,0,0,0.2))')
2323
+ .style('opacity', 0.9);
2288
2324
  tooltip.transition()
2289
2325
  .duration(200)
2290
2326
  .style('opacity', 1);
@@ -2298,10 +2334,12 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2298
2334
  .style('left', (event.pageX + 10) + 'px')
2299
2335
  .style('top', (event.pageY - 28) + 'px');
2300
2336
  })
2301
- .on('mouseout', function () {
2337
+ .on('mouseout', function (event, d) {
2302
2338
  d3.select(this)
2303
2339
  .transition()
2304
- .duration(200)
2340
+ .duration(150)
2341
+ .attr('d', d => arc(d))
2342
+ .style('filter', 'drop-shadow(0 1px 3px rgba(0,0,0,0.12))')
2305
2343
  .style('opacity', 1);
2306
2344
  tooltip.transition()
2307
2345
  .duration(500)
@@ -2311,9 +2349,32 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2311
2349
  const angle = d.x1 - d.x0;
2312
2350
  return angle > 0.15 && d.depth <= 2;
2313
2351
  };
2314
- g.selectAll('text')
2352
+ // Calculate average background color for center text contrast
2353
+ const allSegments = nodes.filter(d => d.depth === 1);
2354
+ const avgColor = allSegments.length > 0 ? d3.interpolateRgb.gamma(2.2)(...allSegments.map(d => getColor(d.data.name, 1)))(0.5) : '#ffffff';
2355
+ const centerTextColor = getTextColor$1(avgColor);
2356
+ // Add center text
2357
+ g.append('text')
2358
+ .attr('text-anchor', 'middle')
2359
+ .attr('alignment-baseline', 'middle')
2360
+ .attr('font-size', '18px')
2361
+ .attr('font-weight', 'bold')
2362
+ .attr('fill', centerTextColor)
2363
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 3px rgba(0,0,0,0.5)' : '0 1px 3px rgba(255,255,255,0.5)')
2364
+ .text(centerLabel || data.name || 'Total');
2365
+ g.append('text')
2366
+ .attr('text-anchor', 'middle')
2367
+ .attr('alignment-baseline', 'middle')
2368
+ .attr('y', 20)
2369
+ .attr('font-size', '14px')
2370
+ .attr('font-weight', '500')
2371
+ .attr('fill', centerTextColor)
2372
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 2px rgba(0,0,0,0.4)' : '0 1px 2px rgba(255,255,255,0.4)')
2373
+ .text(`${(root.value || 0).toLocaleString()} ${unit}`);
2374
+ g.selectAll('text.segment-label')
2315
2375
  .data(nodes.filter(d => d.depth > 0 && d.value && d.value > 0 && shouldDisplayLabel(d)))
2316
2376
  .enter().append('text')
2377
+ .attr('class', 'segment-label')
2317
2378
  .attr('transform', d => {
2318
2379
  const angle = (d.x0 + d.x1) / 2;
2319
2380
  const radius = (Math.sqrt(d.y0) + Math.sqrt(d.y1)) / 2;
@@ -2323,11 +2384,32 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2323
2384
  })
2324
2385
  .attr('text-anchor', 'middle')
2325
2386
  .attr('alignment-baseline', 'middle')
2326
- .attr('font-size', '12px')
2327
- .attr('fill', 'var(--text-inverse)')
2328
- .attr('font-weight', 'var(--font-medium)')
2387
+ .attr('font-size', d => d.depth === 1 ? '13px' : '11px')
2388
+ .attr('fill', d => {
2389
+ let ancestor = d;
2390
+ while (ancestor.depth > 1 && ancestor.parent) {
2391
+ ancestor = ancestor.parent;
2392
+ }
2393
+ const segmentColor = getColor(ancestor.data.name, d.depth);
2394
+ return getTextColor$1(segmentColor);
2395
+ })
2396
+ .attr('font-weight', '600')
2329
2397
  .style('pointer-events', 'none')
2330
- .text(d => d.data.name.substring(0, 10));
2398
+ .style('text-shadow', d => {
2399
+ let ancestor = d;
2400
+ while (ancestor.depth > 1 && ancestor.parent) {
2401
+ ancestor = ancestor.parent;
2402
+ }
2403
+ const segmentColor = getColor(ancestor.data.name, d.depth);
2404
+ const textColor = getTextColor$1(segmentColor);
2405
+ // Use contrasting shadow color
2406
+ const shadowColor = textColor === '#ffffff' ? 'rgba(0,0,0,0.5)' : 'rgba(255,255,255,0.5)';
2407
+ return `0 1px 2px ${shadowColor}`;
2408
+ })
2409
+ .text(d => {
2410
+ const maxLength = d.depth === 1 ? 12 : 8;
2411
+ return d.data.name.substring(0, maxLength);
2412
+ });
2331
2413
  return () => {
2332
2414
  tooltip.remove();
2333
2415
  };
@@ -2338,12 +2420,23 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2338
2420
  var styles = {"container":"PieChart-module_container__tXjbe","title":"PieChart-module_title__61o0R","chartContainer":"PieChart-module_chartContainer__uLmOz","chart":"PieChart-module_chart__3nqON","legend":"PieChart-module_legend__rAWgh","legendItem":"PieChart-module_legendItem__Nb031","legendColor":"PieChart-module_legendColor__fLuv9","legendLabel":"PieChart-module_legendLabel__xbjBr","legendValue":"PieChart-module_legendValue__h2WS2","tooltip":"PieChart-module_tooltip__140RU"};
2339
2421
 
2340
2422
  const DEFAULT_COLORS = [
2341
- '#d4af37', '#FFD700', '#FFA500', '#FF8C00',
2342
- '#FF6347', '#DC143C', '#8B4513', '#A0522D',
2343
- '#DEB887', '#F4A460', '#D2691E', '#CD853F',
2344
- '#B8860B', '#DAA520', '#F0E68C', '#BDB76B'
2423
+ '#6366f1', '#8b5cf6', '#06b6d4', '#10b981',
2424
+ '#f59e0b', '#ef4444', '#ec4899', '#84cc16',
2425
+ '#f97316', '#3b82f6', '#8b5cf6', '#14b8a6',
2426
+ '#f59e0b', '#ef4444', '#06b6d4', '#10b981'
2345
2427
  ];
2346
- const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', showLegend = true }) => {
2428
+ // Calculate text color based on background luminance for optimal contrast
2429
+ const getTextColor = (backgroundColor) => {
2430
+ const color = d3.color(backgroundColor);
2431
+ if (!color)
2432
+ return '#ffffff';
2433
+ const rgb = color.rgb();
2434
+ // Calculate relative luminance using WCAG formula
2435
+ const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
2436
+ // Return white text for dark backgrounds, black for light backgrounds
2437
+ return luminance > 0.5 ? '#000000' : '#ffffff';
2438
+ };
2439
+ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', showLegend = true, unit = 'items', centerLabel }) => {
2347
2440
  const svgRef = useRef(null);
2348
2441
  const radius = Math.min(width, height) / 2 - 20;
2349
2442
  useEffect(() => {
@@ -2357,8 +2450,9 @@ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', sho
2357
2450
  .value(d => d.value)
2358
2451
  .sort(null);
2359
2452
  const arc = d3.arc()
2360
- .innerRadius(0)
2361
- .outerRadius(radius);
2453
+ .innerRadius(radius * 0.4)
2454
+ .outerRadius(radius)
2455
+ .cornerRadius(4);
2362
2456
  const labelArc = d3.arc()
2363
2457
  .innerRadius(radius * 0.7)
2364
2458
  .outerRadius(radius * 0.7);
@@ -2376,13 +2470,19 @@ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', sho
2376
2470
  .attr('d', d => arc(d))
2377
2471
  .attr('fill', (d, i) => d.data.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length])
2378
2472
  .attr('stroke', 'var(--bg-primary)')
2379
- .attr('stroke-width', 2)
2473
+ .attr('stroke-width', 3)
2380
2474
  .style('cursor', 'pointer')
2475
+ .style('filter', 'drop-shadow(0 2px 8px rgba(0,0,0,0.15))')
2381
2476
  .on('mouseover', function (event, d) {
2477
+ const hoverArc = d3.arc()
2478
+ .innerRadius(radius * 0.4)
2479
+ .outerRadius(radius * 1.05)
2480
+ .cornerRadius(4);
2382
2481
  d3.select(this)
2383
2482
  .transition()
2384
2483
  .duration(200)
2385
- .style('opacity', 0.8);
2484
+ .attr('d', d => hoverArc(d))
2485
+ .style('filter', 'drop-shadow(0 4px 12px rgba(0,0,0,0.25))');
2386
2486
  tooltip.transition()
2387
2487
  .duration(200)
2388
2488
  .style('opacity', 1);
@@ -2395,27 +2495,59 @@ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', sho
2395
2495
  .style('left', (event.pageX + 10) + 'px')
2396
2496
  .style('top', (event.pageY - 28) + 'px');
2397
2497
  })
2398
- .on('mouseout', function () {
2498
+ .on('mouseout', function (event, d) {
2399
2499
  d3.select(this)
2400
2500
  .transition()
2401
2501
  .duration(200)
2402
- .style('opacity', 1);
2502
+ .attr('d', d => arc(d))
2503
+ .style('filter', 'drop-shadow(0 2px 8px rgba(0,0,0,0.15))');
2403
2504
  tooltip.transition()
2404
2505
  .duration(500)
2405
2506
  .style('opacity', 0);
2406
2507
  });
2407
- arcs.filter(d => (d.endAngle - d.startAngle) > 0.3)
2508
+ // Calculate average background color for center text contrast
2509
+ const avgColor = data.length > 0 ? d3.interpolateRgb.gamma(2.2)(...data.map((d, i) => d.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length]))(0.5) : '#ffffff';
2510
+ const centerTextColor = getTextColor(avgColor);
2511
+ // Add center text for donut
2512
+ g.append('text')
2513
+ .attr('text-anchor', 'middle')
2514
+ .attr('alignment-baseline', 'middle')
2515
+ .attr('font-size', '20px')
2516
+ .attr('font-weight', 'bold')
2517
+ .attr('fill', centerTextColor)
2518
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 3px rgba(0,0,0,0.5)' : '0 1px 3px rgba(255,255,255,0.5)')
2519
+ .text(centerLabel || 'Total');
2520
+ g.append('text')
2521
+ .attr('text-anchor', 'middle')
2522
+ .attr('alignment-baseline', 'middle')
2523
+ .attr('y', 22)
2524
+ .attr('font-size', '16px')
2525
+ .attr('font-weight', '600')
2526
+ .attr('fill', centerTextColor)
2527
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 2px rgba(0,0,0,0.4)' : '0 1px 2px rgba(255,255,255,0.4)')
2528
+ .text(`${total.toLocaleString()} ${unit}`);
2529
+ arcs.filter(d => (d.endAngle - d.startAngle) > 0.2)
2408
2530
  .append('text')
2409
2531
  .attr('transform', d => `translate(${labelArc.centroid(d)})`)
2410
2532
  .attr('text-anchor', 'middle')
2411
2533
  .attr('alignment-baseline', 'middle')
2412
- .attr('font-size', '12px')
2413
- .attr('fill', 'var(--text-inverse)')
2414
- .attr('font-weight', 'var(--font-semibold)')
2534
+ .attr('font-size', '13px')
2535
+ .attr('fill', (d, i) => {
2536
+ const segmentColor = d.data.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length];
2537
+ return getTextColor(segmentColor);
2538
+ })
2539
+ .attr('font-weight', '600')
2415
2540
  .style('pointer-events', 'none')
2541
+ .style('text-shadow', (d, i) => {
2542
+ const segmentColor = d.data.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length];
2543
+ const textColor = getTextColor(segmentColor);
2544
+ // Use contrasting shadow color
2545
+ const shadowColor = textColor === '#ffffff' ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.4)';
2546
+ return `0 1px 2px ${shadowColor}`;
2547
+ })
2416
2548
  .text(d => {
2417
2549
  const percentage = ((d.data.value / total) * 100);
2418
- return percentage > 5 ? `${percentage.toFixed(1)}%` : '';
2550
+ return percentage > 8 ? `${percentage.toFixed(0)}%` : '';
2419
2551
  });
2420
2552
  return () => {
2421
2553
  tooltip.remove();