@dropins/storefront-company-switcher 1.0.0-alpha2 → 1.0.0-beta2

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,23 +1,5 @@
1
- /********************************************************************
2
- * Copyright 2025 Adobe
3
- * All Rights Reserved.
4
- *
5
- * NOTICE: Adobe permits you to use, modify, and distribute this
6
- * file in accordance with the terms of the Adobe license agreement
7
- * accompanying it.
8
- *******************************************************************/
9
- interface Company {
10
- id: string;
11
- name: string;
12
- }
13
- interface CompanyOption {
14
- text: string;
15
- value: string;
16
- }
17
- interface CustomerCompanyInfo {
18
- currentCompany: Company | null;
19
- customerCompanies: CompanyOption[];
20
- }
1
+ import { CustomerCompanyInfo } from '../../types/company';
2
+
21
3
  /**
22
4
  * Fetches customer company information including the current company and all available companies
23
5
  *
@@ -25,5 +7,4 @@ interface CustomerCompanyInfo {
25
7
  * @throws Will not throw errors - returns empty data on failure
26
8
  */
27
9
  export declare const getCustomerCompanyInfo: () => Promise<CustomerCompanyInfo>;
28
- export {};
29
10
  //# sourceMappingURL=customerCompanies.d.ts.map
@@ -1,6 +1,6 @@
1
1
  /*! Copyright 2025 Adobe
2
2
  All Rights Reserved. */
3
- import{FetchGraphQL as i}from"@dropins/tools/fetch-graphql.js";const{setEndpoint:l,setFetchGraphQlHeader:C,removeFetchGraphQlHeader:y,setFetchGraphQlHeaders:E,fetchGraphQl:m,getConfig:p}=new i().getMethods(),u=`
3
+ import{FetchGraphQL as c}from"@dropins/tools/fetch-graphql.js";const{setEndpoint:f,setFetchGraphQlHeader:l,removeFetchGraphQlHeader:C,setFetchGraphQlHeaders:y,fetchGraphQl:i,getConfig:m}=new c().getMethods(),p=`
4
4
  query GET_CUSTOMER_COMPANIES {
5
5
  customer {
6
6
  companies {
@@ -15,5 +15,5 @@ import{FetchGraphQL as i}from"@dropins/tools/fetch-graphql.js";const{setEndpoint
15
15
  id
16
16
  }
17
17
  }
18
- `,n={currentCompany:null,customerCompanies:[]},h=e=>({text:e.name,value:e.id}),d=()=>{var o;return!!((o=p().fetchGraphQlHeaders)!=null&&o.Authorization)},G=async()=>{var e,o;if(!d())return n;try{const t=await m(u);if(!(t!=null&&t.data))return console.error("Invalid GraphQL response structure"),n;const a=t.data,s=a.company,r=a.customer,c=((o=(e=r==null?void 0:r.companies)==null?void 0:e.items)==null?void 0:o.map(h))||[];return{currentCompany:s,customerCompanies:c}}catch(t){return console.error("Failed to fetch customer company information:",t),n}};export{C as a,E as b,p as c,m as f,G as g,y as r,l as s};
18
+ `,a={currentCompany:null,customerCompanies:[]},u=t=>({text:t.name,value:t.id}),h=()=>{var o;return!!((o=m().fetchGraphQlHeaders)!=null&&o.Authorization)},E=async()=>{var t,o;if(!h())return a;try{const e=await i(p);if(!(e!=null&&e.data))return console.error("Invalid GraphQL response structure"),a;const n=e.data.company,r=e.data.customer,s=((o=(t=r==null?void 0:r.companies)==null?void 0:t.items)==null?void 0:o.map(u))||[];return{currentCompany:n,customerCompanies:s}}catch(e){return console.error("Failed to fetch customer company information:",e),a}};export{l as a,y as b,m as c,i as f,E as g,C as r,f as s};
19
19
  //# sourceMappingURL=customerCompanies.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"customerCompanies.js","sources":["/@dropins/storefront-company-switcher/src/api/fetch-graphql/fetch-graphql.ts","/@dropins/storefront-company-switcher/src/api/customerCompanies/customerCompanies.ts"],"sourcesContent":["import { FetchGraphQL } from '@adobe-commerce/fetch-graphql';\n\nexport const {\n setEndpoint,\n setFetchGraphQlHeader,\n removeFetchGraphQlHeader,\n setFetchGraphQlHeaders,\n fetchGraphQl,\n getConfig,\n} = new FetchGraphQL().getMethods();\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { fetchGraphQl, getConfig } from \"@/company-switcher/api\";\n\n// Types\ninterface Company {\n id: string;\n name: string;\n}\n\ninterface CompanyOption {\n text: string;\n value: string;\n}\n\ninterface CustomerCompanyInfo {\n currentCompany: Company | null;\n customerCompanies: CompanyOption[];\n}\n\ninterface GraphQLResponseData {\n customer: {\n companies: {\n items: Company[];\n };\n };\n company: Company | null;\n}\n\ninterface GraphQLResponse {\n data: GraphQLResponseData;\n}\n\n// GraphQL Query\nconst GET_CUSTOMER_COMPANIES_QUERY = `\n query GET_CUSTOMER_COMPANIES {\n customer {\n companies {\n items {\n name\n id\n }\n }\n }\n company {\n name\n id\n }\n }\n`;\n\n// Constants\nconst EMPTY_COMPANY_INFO: CustomerCompanyInfo = {\n currentCompany: null,\n customerCompanies: []\n};\n\n/**\n * Transforms a company object into a company option for UI components\n */\nconst transformCompanyToOption = (company: Company): CompanyOption => ({\n text: company.name,\n value: company.id\n});\n\n/**\n * Checks if the user is authenticated by verifying the Authorization header\n */\nconst isUserAuthenticated = (): boolean => {\n const config = getConfig();\n return Boolean(config.fetchGraphQlHeaders?.Authorization);\n};\n\n/**\n * Fetches customer company information including the current company and all available companies\n * \n * @returns Promise containing current company and list of available companies\n * @throws Will not throw errors - returns empty data on failure\n */\nexport const getCustomerCompanyInfo = async (): Promise<CustomerCompanyInfo> => {\n // Return empty data if user is not authenticated\n if (!isUserAuthenticated()) {\n return EMPTY_COMPANY_INFO;\n }\n\n try {\n // Fetch company data from GraphQL API\n const response = await fetchGraphQl<GraphQLResponse>(GET_CUSTOMER_COMPANIES_QUERY);\n \n if (!response?.data) {\n console.error('Invalid GraphQL response structure');\n return EMPTY_COMPANY_INFO;\n }\n\n const responseData = response.data as any as GraphQLResponseData;\n const currentCompany = responseData.company;\n const customer = responseData.customer;\n \n // Transform company items to options for UI components\n const customerCompanies = customer?.companies?.items?.map(transformCompanyToOption) || [];\n\n return {\n currentCompany,\n customerCompanies\n };\n } catch (error) {\n // Log error for debugging but don't expose to UI\n console.error('Failed to fetch customer company information:', error);\n return EMPTY_COMPANY_INFO;\n }\n};\n\n"],"names":["setEndpoint","setFetchGraphQlHeader","removeFetchGraphQlHeader","setFetchGraphQlHeaders","fetchGraphQl","getConfig","FetchGraphQL","GET_CUSTOMER_COMPANIES_QUERY","EMPTY_COMPANY_INFO","transformCompanyToOption","company","isUserAuthenticated","_a","getCustomerCompanyInfo","response","responseData","currentCompany","customer","customerCompanies","_b","error"],"mappings":"+DAEO,KAAM,CACX,YAAAA,EACA,sBAAAC,EACA,yBAAAC,EACA,uBAAAC,EACA,aAAAC,EACA,UAAAC,CACF,EAAI,IAAIC,EAAA,EAAe,WAAA,ECgCjBC,EAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkB/BC,EAA0C,CAC9C,eAAgB,KAChB,kBAAmB,CAAA,CACrB,EAKMC,EAA4BC,IAAqC,CACrE,KAAMA,EAAQ,KACd,MAAOA,EAAQ,EACjB,GAKMC,EAAsB,IAAe,OAEzC,MAAO,IAAQC,EADAP,EAAA,EACO,sBAAP,MAAAO,EAA4B,cAC7C,EAQaC,EAAyB,SAA0C,SAE9E,GAAI,CAACF,IACH,OAAOH,EAGT,GAAI,CAEF,MAAMM,EAAW,MAAMV,EAA8BG,CAA4B,EAEjF,GAAI,EAACO,GAAA,MAAAA,EAAU,MACb,eAAQ,MAAM,oCAAoC,EAC3CN,EAGT,MAAMO,EAAeD,EAAS,KACxBE,EAAiBD,EAAa,QAC9BE,EAAWF,EAAa,SAGxBG,IAAoBC,GAAAP,EAAAK,GAAA,YAAAA,EAAU,YAAV,YAAAL,EAAqB,QAArB,YAAAO,EAA4B,IAAIV,KAA6B,CAAA,EAEvF,MAAO,CACL,eAAAO,EACA,kBAAAE,CAAA,CAEJ,OAASE,EAAO,CAEd,eAAQ,MAAM,gDAAiDA,CAAK,EAC7DZ,CACT,CACF"}
1
+ {"version":3,"file":"customerCompanies.js","sources":["/@dropins/storefront-company-switcher/src/api/fetch-graphql/fetch-graphql.ts","/@dropins/storefront-company-switcher/src/api/customerCompanies/customerCompanies.ts"],"sourcesContent":["import { FetchGraphQL } from '@adobe-commerce/fetch-graphql';\n\nexport const {\n setEndpoint,\n setFetchGraphQlHeader,\n removeFetchGraphQlHeader,\n setFetchGraphQlHeaders,\n fetchGraphQl,\n getConfig,\n} = new FetchGraphQL().getMethods();\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { fetchGraphQl, getConfig } from \"@/company-switcher/api\";\nimport type { Company, CompanyOption, CustomerCompanyInfo, GraphQLResponse } from '@/company-switcher/types/company';\n\n// GraphQL Query\nconst GET_CUSTOMER_COMPANIES_QUERY = `\n query GET_CUSTOMER_COMPANIES {\n customer {\n companies {\n items {\n name\n id\n }\n }\n }\n company {\n name\n id\n }\n }\n`;\n\n// Constants\nconst EMPTY_COMPANY_INFO: CustomerCompanyInfo = {\n currentCompany: null,\n customerCompanies: []\n};\n\n/**\n * Transforms a company object into a company option for UI components\n */\nconst transformCompanyToOption = (company: Company): CompanyOption => ({\n text: company.name,\n value: company.id\n});\n\n/**\n * Checks if the user is authenticated by verifying the Authorization header\n */\nconst isUserAuthenticated = (): boolean => {\n const config = getConfig();\n return Boolean(config.fetchGraphQlHeaders?.Authorization);\n};\n\n/**\n * Fetches customer company information including the current company and all available companies\n * \n * @returns Promise containing current company and list of available companies\n * @throws Will not throw errors - returns empty data on failure\n */\nexport const getCustomerCompanyInfo = async (): Promise<CustomerCompanyInfo> => {\n // Return empty data if user is not authenticated\n if (!isUserAuthenticated()) {\n return EMPTY_COMPANY_INFO;\n }\n\n try {\n // Fetch company data from GraphQL API\n const response = await fetchGraphQl<GraphQLResponse>(GET_CUSTOMER_COMPANIES_QUERY);\n \n if (!response?.data) {\n console.error('Invalid GraphQL response structure');\n return EMPTY_COMPANY_INFO;\n }\n\n const currentCompany = (response as any).data.company;\n const customer = (response as any).data.customer;\n \n // Transform company items to options for UI components\n const customerCompanies = customer?.companies?.items?.map(transformCompanyToOption) || [];\n\n return {\n currentCompany,\n customerCompanies\n };\n } catch (error) {\n // Log error for debugging but don't expose to UI\n console.error('Failed to fetch customer company information:', error);\n return EMPTY_COMPANY_INFO;\n }\n};\n\n"],"names":["setEndpoint","setFetchGraphQlHeader","removeFetchGraphQlHeader","setFetchGraphQlHeaders","fetchGraphQl","getConfig","FetchGraphQL","GET_CUSTOMER_COMPANIES_QUERY","EMPTY_COMPANY_INFO","transformCompanyToOption","company","isUserAuthenticated","_a","getCustomerCompanyInfo","response","currentCompany","customer","customerCompanies","_b","error"],"mappings":"+DAEO,KAAM,CACX,YAAAA,EACA,sBAAAC,EACA,yBAAAC,EACA,uBAAAC,EACA,aAAAC,EACA,UAAAC,CACF,EAAI,IAAIC,EAAA,EAAe,WAAA,ECIjBC,EAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkB/BC,EAA0C,CAC9C,eAAgB,KAChB,kBAAmB,CAAA,CACrB,EAKMC,EAA4BC,IAAqC,CACrE,KAAMA,EAAQ,KACd,MAAOA,EAAQ,EACjB,GAKMC,EAAsB,IAAe,OAEzC,MAAO,IAAQC,EADAP,EAAA,EACO,sBAAP,MAAAO,EAA4B,cAC7C,EAQaC,EAAyB,SAA0C,SAE9E,GAAI,CAACF,IACH,OAAOH,EAGT,GAAI,CAEF,MAAMM,EAAW,MAAMV,EAA8BG,CAA4B,EAEjF,GAAI,EAACO,GAAA,MAAAA,EAAU,MACb,eAAQ,MAAM,oCAAoC,EAC3CN,EAGT,MAAMO,EAAkBD,EAAiB,KAAK,QACxCE,EAAYF,EAAiB,KAAK,SAGlCG,IAAoBC,GAAAN,EAAAI,GAAA,YAAAA,EAAU,YAAV,YAAAJ,EAAqB,QAArB,YAAAM,EAA4B,IAAIT,KAA6B,CAAA,EAEvF,MAAO,CACL,eAAAM,EACA,kBAAAE,CAAA,CAEJ,OAASE,EAAO,CAEd,eAAQ,MAAM,gDAAiDA,CAAK,EAC7DX,CACT,CACF"}
@@ -2,10 +2,13 @@ import { HTMLAttributes } from 'preact/compat';
2
2
  import { Container } from '@dropins/tools/types/elsie/src/lib';
3
3
 
4
4
  export interface CompanySwitcherProps extends HTMLAttributes<HTMLDivElement> {
5
+ /** Custom aria-label for the picker */
6
+ ariaLabel?: string;
5
7
  }
6
8
  /**
7
9
  * CompanySwitcher component allows users to switch between companies they have access to.
8
10
  * It only renders when a user has access to multiple companies.
11
+ * This is a presentational component that uses the useCompanyData hook for all business logic.
9
12
  */
10
13
  export declare const CompanySwitcher: Container<CompanySwitcherProps>;
11
14
  //# sourceMappingURL=CompanySwitcher.d.ts.map
@@ -7,5 +7,6 @@
7
7
  * accompanying it.
8
8
  *******************************************************************/
9
9
  export * from './CompanySwitcher';
10
+ export * from './useCompanyData';
10
11
  export { CompanySwitcher as default } from './CompanySwitcher';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { UseCompanyDataReturn } from '../../types/company';
2
+
3
+ /**
4
+ * Custom hook that manages company data fetching and state management
5
+ * @returns {UseCompanyDataReturn} Company data and handlers
6
+ */
7
+ export declare const useCompanyData: () => UseCompanyDataReturn;
8
+ //# sourceMappingURL=useCompanyData.d.ts.map
@@ -1,4 +1,4 @@
1
1
  /*! Copyright 2025 Adobe
2
2
  All Rights Reserved. */
3
- import{jsx as d}from"@dropins/tools/preact-jsx-runtime.js";import{useState as y,useCallback as o,useEffect as I}from"@dropins/tools/preact-hooks.js";import{Picker as v}from"@dropins/tools/components.js";import{events as a}from"@dropins/tools/event-bus.js";import{g as x}from"../chunks/customerCompanies.js";import{setFetchGraphQlHeader as f,removeFetchGraphQlHeader as E}from"@dropins/tools/fetch-graphql.js";const r="X-Adobe-Company",s="DROPIN__COMPANYSWITCHER__COMPANY__CONTEXT",H=({children:A,initialData:O,...h})=>{const[c,m]=y([]),[g,i]=y({text:"",value:""}),p=o(async()=>{var t,n;try{const e=await x();m(e.customerCompanies),(t=e.currentCompany)!=null&&t.name&&((n=e.currentCompany)!=null&&n.id)&&i({text:e.currentCompany.name,value:e.currentCompany.id})}catch(e){console.error("Failed to load company data:",e)}},[]),_=o(t=>{const e=t.target.value;a.emit("companyContext/changed",e),a.emit("checkout/updated",!0),sessionStorage.setItem(s,e),f(r,e)},[]),u=o(()=>{const t=sessionStorage.getItem(s);t&&f(r,t)},[]),C=o(()=>{E(r),sessionStorage.removeItem(s),m([]),i({text:"",value:""})},[]),l=o(async t=>{t?(u(),await p()):C()},[p,u,C]);return I(()=>{const t=a.on("authenticated",l,{eager:!0});return()=>{t&&typeof t=="function"&&t()}},[l]),c.length<2?null:d("div",{...h,children:d(v,{options:c,defaultOption:g,onChange:_})})};export{H as CompanySwitcher,H as default};
3
+ import{jsx as f}from"@dropins/tools/preact-jsx-runtime.js";import{useState as u,useCallback as p,useEffect as g,useMemo as v}from"@dropins/tools/preact-hooks.js";import{Picker as x}from"@dropins/tools/components.js";import{events as C}from"@dropins/tools/event-bus.js";import{g as w}from"../chunks/customerCompanies.js";import"@dropins/tools/fetch-graphql.js";const I=()=>{const[r,m]=u([]),[c,a]=u({text:"",value:""}),i=p(async()=>{var e,n;try{const t=await w();m(t.customerCompanies),(e=t.currentCompany)!=null&&e.name&&((n=t.currentCompany)!=null&&n.id)&&a({text:t.currentCompany.name,value:t.currentCompany.id})}catch(t){console.error("Failed to load company data:",t)}},[]),s=p(e=>{const t=e.target.value,o=r.find(h=>h.value===t);o&&a(o),C.emit("companyContext/changed",t)},[r]),l=p(()=>{m([]),a({text:"",value:""})},[]),y=p(e=>{e?i():l()},[i,l]),d=p(e=>{m(n=>{const t=n.find(o=>o.value===e);return t&&a(t),n})},[]);return g(()=>{const e=C.on("authenticated",y,{eager:!0}),n=C.on("companyContext/restored",d);return()=>{var t,o;(t=e==null?void 0:e.off)==null||t.call(e),(o=n==null?void 0:n.off)==null||o.call(n)}},[y,d]),{companies:r,currentCompany:c,handleCompanyChange:s}},F=({ariaLabel:r,...m})=>{const{companies:c,currentCompany:a,handleCompanyChange:i}=I(),s=v(()=>c,[c]);return c.length<2?null:f("div",{...m,children:f(x,{options:s,value:a.value,onChange:i,"aria-label":r||"Select company","aria-describedby":"company-switcher-description"})})};export{F as CompanySwitcher,F as default,I as useCompanyData};
4
4
  //# sourceMappingURL=CompanySwitcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CompanySwitcher.js","sources":["/@dropins/storefront-company-switcher/src/containers/CompanySwitcher/CompanySwitcher.tsx"],"sourcesContent":["/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n \nimport { HTMLAttributes } from 'preact/compat';\nimport { useState, useEffect, useCallback } from 'preact/hooks';\nimport { Container } from '@adobe-commerce/elsie/lib';\nimport { Picker } from '@adobe-commerce/elsie/components';\nimport { events } from '@adobe-commerce/event-bus';\nimport { getCustomerCompanyInfo } from '@/company-switcher/api';\nimport { setFetchGraphQlHeader, removeFetchGraphQlHeader } from '@adobe-commerce/fetch-graphql';\n\nconst COMPANY_HEADER_KEY = 'X-Adobe-Company';\nconst STORAGE_KEY = 'DROPIN__COMPANYSWITCHER__COMPANY__CONTEXT';\n\ninterface Company {\n id: string;\n name: string;\n}\n\ninterface CompanyOption {\n text: string;\n value: string;\n}\n\ninterface CustomerCompanyInfo {\n currentCompany: Company | null;\n customerCompanies: CompanyOption[];\n}\n\nexport interface CompanySwitcherProps extends HTMLAttributes<HTMLDivElement> {}\n\n/**\n * CompanySwitcher component allows users to switch between companies they have access to.\n * It only renders when a user has access to multiple companies.\n */\nexport const CompanySwitcher: Container<CompanySwitcherProps> = ({ \n children, \n initialData: _initialData, \n ...props \n}) => {\n const [companies, setCompanies] = useState<CompanyOption[]>([]);\n const [currentCompany, setCurrentCompany] = useState<CompanyOption>({ text: '', value: '' });\n\n /**\n * Loads company information from the API and updates state\n */\n const loadCompanyData = useCallback(async (): Promise<void> => {\n try {\n const companyInfo: CustomerCompanyInfo = await getCustomerCompanyInfo();\n setCompanies(companyInfo.customerCompanies);\n \n // Set current company if it has valid name and id\n if (companyInfo.currentCompany?.name && companyInfo.currentCompany?.id) {\n setCurrentCompany({\n text: companyInfo.currentCompany.name, \n value: companyInfo.currentCompany.id\n });\n }\n } catch (error) {\n console.error('Failed to load company data:', error);\n // State already initialized with empty values, no additional action needed\n }\n }, []);\n\n /**\n * Handles company selection change\n */\n const handleCompanyChange = useCallback((event: Event): void => {\n const target = event.target as HTMLSelectElement;\n const companyId = target.value;\n \n // Emit event for other components to react to company change\n events.emit('companyContext/changed', companyId);\n \n // Trick cart drop into refreshing cart data.\n events.emit('checkout/updated', true);\n \n // Persist selection\n sessionStorage.setItem(STORAGE_KEY, companyId);\n \n // Update GraphQL header for subsequent requests\n setFetchGraphQlHeader(COMPANY_HEADER_KEY, companyId);\n }, []);\n\n /**\n * Restores company context from session storage\n */\n const restoreCompanyContext = useCallback((): void => {\n const storedCompanyId = sessionStorage.getItem(STORAGE_KEY);\n if (storedCompanyId) {\n setFetchGraphQlHeader(COMPANY_HEADER_KEY, storedCompanyId);\n }\n }, []);\n\n /**\n * Clears company context\n */\n const clearCompanyContext = useCallback((): void => {\n removeFetchGraphQlHeader(COMPANY_HEADER_KEY);\n sessionStorage.removeItem(STORAGE_KEY);\n setCompanies([]);\n setCurrentCompany({ text: '', value: '' });\n }, []);\n\n /**\n * Handles authentication state changes\n */\n const handleAuthenticationChange = useCallback(async (authenticated: boolean): Promise<void> => {\n if (authenticated) {\n restoreCompanyContext();\n await loadCompanyData();\n } else {\n clearCompanyContext();\n }\n }, [loadCompanyData, restoreCompanyContext, clearCompanyContext]);\n\n // Subscribe to authentication events\n useEffect(() => {\n const unsubscribe: any = events.on('authenticated', handleAuthenticationChange, { eager: true });\n \n // Cleanup subscription on unmount\n return () => {\n if (unsubscribe && typeof unsubscribe === 'function') {\n unsubscribe();\n }\n };\n }, [handleAuthenticationChange]);\n\n // Only render if user has access to multiple companies\n if (companies.length < 2) {\n return null;\n }\n\n return (\n <div {...props}>\n <Picker \n options={companies} \n defaultOption={currentCompany} \n onChange={handleCompanyChange}\n />\n </div>\n );\n};\n"],"names":["COMPANY_HEADER_KEY","STORAGE_KEY","CompanySwitcher","children","_initialData","props","companies","setCompanies","useState","currentCompany","setCurrentCompany","loadCompanyData","useCallback","companyInfo","getCustomerCompanyInfo","_a","_b","error","handleCompanyChange","event","companyId","events","setFetchGraphQlHeader","restoreCompanyContext","storedCompanyId","clearCompanyContext","removeFetchGraphQlHeader","handleAuthenticationChange","authenticated","useEffect","unsubscribe","jsx","Picker"],"mappings":"yZAiBA,MAAMA,EAAqB,kBACrBC,EAAc,4CAuBPC,EAAmD,CAAC,CAC/D,SAAAC,EACA,YAAaC,EACb,GAAGC,CACL,IAAM,CACJ,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAA0B,CAAA,CAAE,EACxD,CAACC,EAAgBC,CAAiB,EAAIF,EAAwB,CAAE,KAAM,GAAI,MAAO,GAAI,EAKrFG,EAAkBC,EAAY,SAA2B,SAC7D,GAAI,CACF,MAAMC,EAAmC,MAAMC,EAAA,EAC/CP,EAAaM,EAAY,iBAAiB,GAGtCE,EAAAF,EAAY,iBAAZ,MAAAE,EAA4B,QAAQC,EAAAH,EAAY,iBAAZ,MAAAG,EAA4B,KAClEN,EAAkB,CAChB,KAAMG,EAAY,eAAe,KACjC,MAAOA,EAAY,eAAe,EAAA,CACnC,CAEL,OAASI,EAAO,CACd,QAAQ,MAAM,+BAAgCA,CAAK,CAErD,CACF,EAAG,CAAA,CAAE,EAKCC,EAAsBN,EAAaO,GAAuB,CAE9D,MAAMC,EADSD,EAAM,OACI,MAGzBE,EAAO,KAAK,yBAA0BD,CAAS,EAG/CC,EAAO,KAAK,mBAAoB,EAAI,EAGpC,eAAe,QAAQpB,EAAamB,CAAS,EAG7CE,EAAsBtB,EAAoBoB,CAAS,CACrD,EAAG,CAAA,CAAE,EAKCG,EAAwBX,EAAY,IAAY,CACpD,MAAMY,EAAkB,eAAe,QAAQvB,CAAW,EACtDuB,GACFF,EAAsBtB,EAAoBwB,CAAe,CAE7D,EAAG,CAAA,CAAE,EAKCC,EAAsBb,EAAY,IAAY,CAClDc,EAAyB1B,CAAkB,EAC3C,eAAe,WAAWC,CAAW,EACrCM,EAAa,CAAA,CAAE,EACfG,EAAkB,CAAE,KAAM,GAAI,MAAO,GAAI,CAC3C,EAAG,CAAA,CAAE,EAKCiB,EAA6Bf,EAAY,MAAOgB,GAA0C,CAC1FA,GACFL,EAAA,EACA,MAAMZ,EAAA,GAENc,EAAA,CAEJ,EAAG,CAACd,EAAiBY,EAAuBE,CAAmB,CAAC,EAehE,OAZAI,EAAU,IAAM,CACd,MAAMC,EAAmBT,EAAO,GAAG,gBAAiBM,EAA4B,CAAE,MAAO,GAAM,EAG/F,MAAO,IAAM,CACPG,GAAe,OAAOA,GAAgB,YACxCA,EAAA,CAEJ,CACF,EAAG,CAACH,CAA0B,CAAC,EAG3BrB,EAAU,OAAS,EACd,KAIPyB,EAAC,MAAA,CAAK,GAAG1B,EACP,SAAA0B,EAACC,EAAA,CACC,QAAS1B,EACT,cAAeG,EACf,SAAUS,CAAA,CAAA,EAEd,CAEJ"}
1
+ {"version":3,"file":"CompanySwitcher.js","sources":["/@dropins/storefront-company-switcher/src/containers/CompanySwitcher/useCompanyData.ts","/@dropins/storefront-company-switcher/src/containers/CompanySwitcher/CompanySwitcher.tsx"],"sourcesContent":["/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { useState, useCallback, useEffect } from 'preact/hooks';\nimport { events } from '@adobe-commerce/event-bus';\nimport { getCustomerCompanyInfo } from '@/company-switcher/api';\nimport type { CompanyOption, CustomerCompanyInfo, UseCompanyDataReturn } from '@/company-switcher/types/company';\n\n/**\n * Custom hook that manages company data fetching and state management\n * @returns {UseCompanyDataReturn} Company data and handlers\n */\nexport const useCompanyData = (): UseCompanyDataReturn => {\n const [companies, setCompanies] = useState<CompanyOption[]>([]);\n const [currentCompany, setCurrentCompany] = useState<CompanyOption>({ text: '', value: '' });\n\n\n /**\n * Loads company information from the API and updates state\n */\n const loadCompanyData = useCallback(async (): Promise<void> => {\n try {\n const companyInfo: CustomerCompanyInfo = await getCustomerCompanyInfo();\n setCompanies(companyInfo.customerCompanies);\n \n if (companyInfo.currentCompany?.name && companyInfo.currentCompany?.id) {\n setCurrentCompany({\n text: companyInfo.currentCompany.name, \n value: companyInfo.currentCompany.id\n });\n }\n } catch (err) {\n console.error('Failed to load company data:', err);\n }\n }, []);\n\n /**\n * Handles company selection change\n */\n const handleCompanyChange = useCallback((event: Event): void => {\n const target = event.target as HTMLSelectElement;\n const companyId = target.value;\n \n // Update local state\n const selectedCompany = companies.find(c => c.value === companyId);\n if (selectedCompany) {\n setCurrentCompany(selectedCompany);\n }\n \n // Emit event for other components to react to company change\n events.emit('companyContext/changed', companyId);\n }, [companies]);\n\n /**\n * Clears company context\n */\n const clearCompanyContext = useCallback((): void => {\n setCompanies([]);\n setCurrentCompany({ text: '', value: '' });\n }, []);\n\n /**\n * Handles authentication state changes\n */\n const handleAuthenticationChange = useCallback((authenticated: boolean) => {\n if (authenticated) {\n loadCompanyData();\n } else {\n clearCompanyContext();\n }\n }, [loadCompanyData, clearCompanyContext]);\n\n /**\n * Handles company context restoration\n */\n const handleCompanyContextRestored = useCallback((companyId: string) => {\n // Store the company ID to be restored when companies are loaded\n setCompanies(prevCompanies => {\n const restoredCompany = prevCompanies.find(company => company.value === companyId);\n if (restoredCompany) {\n setCurrentCompany(restoredCompany);\n }\n return prevCompanies;\n });\n }, []);\n\n // Set up event listeners\n useEffect(() => {\n const unsubscribeAuth = events.on('authenticated', handleAuthenticationChange, { eager: true });\n const unsubscribeRestore = events.on('companyContext/restored', handleCompanyContextRestored);\n \n return () => {\n unsubscribeAuth?.off?.();\n unsubscribeRestore?.off?.();\n };\n }, [handleAuthenticationChange, handleCompanyContextRestored]);\n\n return {\n companies,\n currentCompany,\n handleCompanyChange\n };\n};\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n \nimport { HTMLAttributes } from 'preact/compat';\nimport { useMemo } from 'preact/hooks';\nimport { Container } from '@adobe-commerce/elsie/lib';\nimport { Picker } from '@adobe-commerce/elsie/components';\nimport { useCompanyData } from './useCompanyData';\n\nexport interface CompanySwitcherProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom aria-label for the picker */\n ariaLabel?: string;\n}\n\n/**\n * CompanySwitcher component allows users to switch between companies they have access to.\n * It only renders when a user has access to multiple companies.\n * This is a presentational component that uses the useCompanyData hook for all business logic.\n */\nexport const CompanySwitcher: Container<CompanySwitcherProps> = ({ \n ariaLabel,\n ...props \n}) => {\n const { companies, currentCompany, handleCompanyChange } = useCompanyData();\n\n // Memoize the companies array to prevent unnecessary re-renders\n const memoizedCompanies = useMemo(() => companies, [companies]);\n\n // Only render if user has access to multiple companies\n if (companies.length < 2) {\n return null;\n }\n\n return (\n <div {...props}>\n <Picker \n options={memoizedCompanies} \n value={currentCompany.value} \n onChange={handleCompanyChange}\n aria-label={ariaLabel || 'Select company'}\n aria-describedby=\"company-switcher-description\"\n />\n </div>\n );\n};\n"],"names":["useCompanyData","companies","setCompanies","useState","currentCompany","setCurrentCompany","loadCompanyData","useCallback","companyInfo","getCustomerCompanyInfo","_a","_b","err","handleCompanyChange","event","companyId","selectedCompany","c","events","clearCompanyContext","handleAuthenticationChange","authenticated","handleCompanyContextRestored","prevCompanies","restoredCompany","company","useEffect","unsubscribeAuth","unsubscribeRestore","CompanySwitcher","ariaLabel","props","memoizedCompanies","useMemo","jsx","Picker"],"mappings":"wWAkBO,MAAMA,EAAiB,IAA4B,CACxD,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAA0B,CAAA,CAAE,EACxD,CAACC,EAAgBC,CAAiB,EAAIF,EAAwB,CAAE,KAAM,GAAI,MAAO,GAAI,EAMrFG,EAAkBC,EAAY,SAA2B,SAC7D,GAAI,CACF,MAAMC,EAAmC,MAAMC,EAAA,EAC/CP,EAAaM,EAAY,iBAAiB,GAEtCE,EAAAF,EAAY,iBAAZ,MAAAE,EAA4B,QAAQC,EAAAH,EAAY,iBAAZ,MAAAG,EAA4B,KAClEN,EAAkB,CAChB,KAAMG,EAAY,eAAe,KACjC,MAAOA,EAAY,eAAe,EAAA,CACnC,CAEL,OAASI,EAAK,CACZ,QAAQ,MAAM,+BAAgCA,CAAG,CACnD,CACF,EAAG,CAAA,CAAE,EAKCC,EAAsBN,EAAaO,GAAuB,CAE9D,MAAMC,EADSD,EAAM,OACI,MAGnBE,EAAkBf,EAAU,KAAKgB,GAAKA,EAAE,QAAUF,CAAS,EAC7DC,GACFX,EAAkBW,CAAe,EAInCE,EAAO,KAAK,yBAA0BH,CAAS,CACjD,EAAG,CAACd,CAAS,CAAC,EAKRkB,EAAsBZ,EAAY,IAAY,CAClDL,EAAa,CAAA,CAAE,EACfG,EAAkB,CAAE,KAAM,GAAI,MAAO,GAAI,CAC3C,EAAG,CAAA,CAAE,EAKCe,EAA6Bb,EAAac,GAA2B,CACrEA,EACFf,EAAA,EAEAa,EAAA,CAEJ,EAAG,CAACb,EAAiBa,CAAmB,CAAC,EAKnCG,EAA+Bf,EAAaQ,GAAsB,CAEtEb,EAAaqB,GAAiB,CAC5B,MAAMC,EAAkBD,EAAc,KAAKE,GAAWA,EAAQ,QAAUV,CAAS,EACjF,OAAIS,GACFnB,EAAkBmB,CAAe,EAE5BD,CACT,CAAC,CACH,EAAG,CAAA,CAAE,EAGL,OAAAG,EAAU,IAAM,CACd,MAAMC,EAAkBT,EAAO,GAAG,gBAAiBE,EAA4B,CAAE,MAAO,GAAM,EACxFQ,EAAqBV,EAAO,GAAG,0BAA2BI,CAA4B,EAE5F,MAAO,IAAM,UACXZ,EAAAiB,GAAA,YAAAA,EAAiB,MAAjB,MAAAjB,EAAA,KAAAiB,IACAhB,EAAAiB,GAAA,YAAAA,EAAoB,MAApB,MAAAjB,EAAA,KAAAiB,EACF,CACF,EAAG,CAACR,EAA4BE,CAA4B,CAAC,EAEtD,CACL,UAAArB,EACA,eAAAG,EACA,oBAAAS,CAAA,CAEJ,ECnFagB,EAAmD,CAAC,CAC/D,UAAAC,EACA,GAAGC,CACL,IAAM,CACJ,KAAM,CAAE,UAAA9B,EAAW,eAAAG,EAAgB,oBAAAS,CAAA,EAAwBb,EAAA,EAGrDgC,EAAoBC,EAAQ,IAAMhC,EAAW,CAACA,CAAS,CAAC,EAG9D,OAAIA,EAAU,OAAS,EACd,KAIPiC,EAAC,MAAA,CAAK,GAAGH,EACP,SAAAG,EAACC,EAAA,CACC,QAASH,EACT,MAAO5B,EAAe,MACtB,SAAUS,EACV,aAAYiB,GAAa,iBACzB,mBAAiB,8BAAA,CAAA,EAErB,CAEJ"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name": "@dropins/storefront-company-switcher", "version": "1.0.0-alpha2", "@dropins/tools": "^1.3.0", "license": "SEE LICENSE IN LICENSE.md"}
1
+ {"name": "@dropins/storefront-company-switcher", "version": "1.0.0-beta2", "@dropins/tools": "^1.3.0", "license": "SEE LICENSE IN LICENSE.md"}
@@ -0,0 +1,55 @@
1
+ /********************************************************************
2
+ * Copyright 2025 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+ /**
10
+ * Represents a company entity
11
+ */
12
+ export interface Company {
13
+ id: string;
14
+ name: string;
15
+ }
16
+ /**
17
+ * Represents a company option for the picker component
18
+ */
19
+ export interface CompanyOption {
20
+ text: string;
21
+ value: string;
22
+ }
23
+ /**
24
+ * Contains customer's current company and available companies
25
+ */
26
+ export interface CustomerCompanyInfo {
27
+ currentCompany: Company | null;
28
+ customerCompanies: CompanyOption[];
29
+ }
30
+ /**
31
+ * Return type for the useCompanyData hook
32
+ */
33
+ export interface UseCompanyDataReturn {
34
+ companies: CompanyOption[];
35
+ currentCompany: CompanyOption;
36
+ handleCompanyChange: (event: Event) => void;
37
+ }
38
+ /**
39
+ * GraphQL response data structure
40
+ */
41
+ export interface GraphQLResponseData {
42
+ company: Company | null;
43
+ customer: {
44
+ companies: {
45
+ items: Company[];
46
+ };
47
+ };
48
+ }
49
+ /**
50
+ * GraphQL response wrapper
51
+ */
52
+ export interface GraphQLResponse {
53
+ data: GraphQLResponseData;
54
+ }
55
+ //# sourceMappingURL=company.d.ts.map