diff --git a/.github/actions/setup-vuu-ui/action.yml b/.github/actions/setup-vuu-ui/action.yml new file mode 100644 index 000000000..2262d91e8 --- /dev/null +++ b/.github/actions/setup-vuu-ui/action.yml @@ -0,0 +1,19 @@ +name: Setup Vuu UI +description: "Installs NodeJS and project dependencies" + +runs: + using: 'composite' + steps: + - name: Install NodeJS + uses: actions/setup-node@v3 + with: + node-version: "16" + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.npm + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- + - name: Install dependencies + shell: bash + run: cd ./vuu-ui && npm install diff --git a/.github/workflows/build-ui.yml b/.github/workflows/build-ui.yml index 909389c7e..ee7e024f7 100644 --- a/.github/workflows/build-ui.yml +++ b/.github/workflows/build-ui.yml @@ -6,15 +6,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: "16" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ~/.npm - key: npm-${{ hashFiles('package-lock.json') }} - restore-keys: npm- - - run: cd ./vuu-ui && npm install + - name: Install Node & dependencies + uses: ./.github/actions/setup-vuu-ui - run: cd ./vuu-ui && npm run build diff --git a/.github/workflows/test-ui.yml b/.github/workflows/test-ui.yml index df80c1ce7..464700feb 100644 --- a/.github/workflows/test-ui.yml +++ b/.github/workflows/test-ui.yml @@ -1,26 +1,26 @@ -name: "Test" +name: "Test UI" on: workflow_dispatch: pull_request: jobs: + lint-and-typecheck: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Node & dependencies + uses: ./.github/actions/setup-vuu-ui + - run: cd ./vuu-ui && npm run lint + - run: cd ./vuu-ui && npm run typecheck + vitest: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: "16" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ~/.npm - key: npm-${{ hashFiles('package-lock.json') }} - restore-keys: npm- - - name: Install dependencies - run: cd ./vuu-ui && npm install + - name: Install Node & dependencies + uses: ./.github/actions/setup-vuu-ui - run: cd ./vuu-ui && npm run test:vite cypress-e2e: @@ -31,52 +31,36 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: "16" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ~/.npm - key: npm-${{ hashFiles('package-lock.json') }} - restore-keys: npm- - - name: Install dependencies - run: cd ./vuu-ui && npm install + - name: Install Node & dependencies + uses: ./.github/actions/setup-vuu-ui - name: Run end-to-end tests in Chrome uses: cypress-io/github-action@bd9dda317ed2d4fbffc808ba6cdcd27823b2a13b with: install: false working-directory: ./vuu-ui browser: chrome - build: npm run build - start: npm run showcase - wait-on: "http://localhost:5173" + build: npm run showcase:build + start: npm run showcase:preview + wait-on: "http://localhost:4173" - name: Run end-to-end tests in Edge uses: cypress-io/github-action@bd9dda317ed2d4fbffc808ba6cdcd27823b2a13b with: install: false working-directory: ./vuu-ui browser: edge - build: npm run build - start: npm run showcase - wait-on: "http://localhost:5173" + build: npm run showcase:build + start: npm run showcase:preview + wait-on: "http://localhost:4173" - # ensure the vuu example and showcase still build - vuu-and-showcase-build: + # ensure the vuu example still builds + vuu-app-build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: "16" - - name: Install dependencies - run: cd ./vuu-ui && npm install + - name: Install Node & dependencies + uses: ./.github/actions/setup-vuu-ui - name: Build Vuu Libraries run: cd ./vuu-ui && npm run build - - name: Build showcase - run: cd ./vuu-ui && npm run showcase:build - name: Build Vuu app run: cd ./vuu-ui && npm run build:app diff --git a/.semgrepignore b/.semgrepignore index 7674ce98a..9f52e4cbc 100644 --- a/.semgrepignore +++ b/.semgrepignore @@ -5,7 +5,7 @@ example/main/src/main/resources/certs/cert.pem vuu/src/main/resources/www/ws-example.html example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala -vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts +vuu-ui/packages/vuu-data-local/src/array-data-source/group-utils.ts vuu-ui/packages/vuu-datagrid-extras/src/column-expression-input/column-language-parser/walkExpressionTree.ts vuu-ui/packages/vuu-layout/src/layout-persistence/RemoteLayoutPersistenceManager.ts vuu-ui/packages/vuu-popups/src/menu/useContextMenu.tsx @@ -20,6 +20,7 @@ vuu/src/test/scala/org/finos/vuu/viewport/CreateViewPortScenarioTest.scala vuu/src/test/scala/org/finos/vuu/net/ws/WebSocketServerClientTest.scala vuu/src/test/scala/org/finos/vuu/net/rpc/RpcModuleTest.scala vuu/src/test/resources/ws.html +vuu-ui/sample-apps/standalone-table/scripts/build.mjs vuu-ui/sample-apps/app-vuu-basket-trader/scripts/build.mjs vuu-ui/sample-apps/app-vuu-example/scripts/build.mjs vuu-ui/showcase/scripts/build-docs.mjs diff --git a/example/basket/src/main/resources/static/ftse100.csv b/example/basket/src/main/resources/static/ftse100.csv deleted file mode 100644 index aa0315f95..000000000 --- a/example/basket/src/main/resources/static/ftse100.csv +++ /dev/null @@ -1,100 +0,0 @@ -Symbol,Name,Last Trade,Change,Volume, Weighting -AAL.L,Anglo American PLC,436.35�13:13,�5.35�(1.24%),5799089,0.0278736825813547 -ABF.L,Associated British Foods PLC,"3,435.60�13:12",�7.40�(0.21%),86808,0.000417248060431947 -ADM.L,Admiral Group PLC,"1,627.00�13:13",,86808,0.000417248060431947 -ADN.L,Aberdeen Asset Management PLC,334.00�13:13,�2.50�(0.75%),806880,0.00387831899135251 -AHT.L,Ashtead Group PLC,"1,027.00�13:13",�6.00�(0.59%),331255,0.00159219779580666 -ANTO.L,Antofagasta PLC,484.10�13:13,�11.70�(2.48%),1753976,0.00843059492263598 -ARM.L,ARM Holdings PLC,"1,058.00�13:13",�3.00�(0.28%),475927,0.00228757277736148 -AV.L,Aviva PLC,493.97�13:13,�2.23�(0.45%),2226835,0.0107034211668507 -AZN.L,AstraZeneca PLC,"4,399.50�13:13",�2.50�(0.06%),815133,0.00391798755004232 -BA.L,BAE Systems PLC,478.10�13:13,�4.30�(0.91%),2039934,0.00980506986578636 -BAB.L,Babcock International Group PLC,988.00�13:13,�9.50�(0.97%),209614,0.00100752275066102 -BARC.L,Barclays PLC,226.30�13:13,�1.15�(0.51%),6575664,0.0316063387021032 -BATS.L,British American Tobacco PLC,"3,803.50�13:13",�8.50�(0.22%),465110,0.0022355801929258 -BDEV.L,Barratt Developments PLC,576.00�13:13,�0.50�(0.09%),1044365,0.00501980543997108 -BG.L,BG Group PLC,"1,013.50�13:13",�5.50�(0.55%),1507332,0.00724508516988073 -BKG.L,Berkeley Group Holdings (The) PLC,"3,126.00�13:13",�15.00�(0.48%),95071,0.000456964684744788 -BLND.L,British Land Co PLC,828.06�13:12,�10.44�(1.25%),1802548,0.00866405926683583 -BLT.L,BHP Billiton PLC,881.40�13:13,�4.30�(0.49%),4947287,0.0237794431982097 -BNZL.L,Bunzl PLC,"1,875.40�13:05",�4.60�(0.24%),104541,0.000502482829757812 -BP.L,BP PLC,381.50�13:13,�2.95�(0.78%),10493561,0.0504379547308349 -BRBY.L,Burberry Group PLC,"1,269.00�13:13",�7.00�(0.55%),295647,0.00142104572530785 -BT-A.L,BT Group PLC,489.20�13:13,�3.70�(0.75%),3914982,0.0188176048996174 -CCL.L,Carnival PLC,"3,426.00�13:12",�22.00�(0.64%),86257,0.000414599644602783 -CNA.L,Centrica PLC,212.80�13:13,�0.60�(0.28%),2144540,0.0103078651220939 -CPG.L,Compass Group PLC,"1,054.00�13:08",�5.00�(0.48%),1001167,0.00481217156158961 -CPI.L,Capita PLC,"1,235.00�13:11",�1.00�(0.08%),244591,0.0011756418803464 -CRH.L,CRH PLC,"1,783.20�13:12",�17.80�(0.99%),897325,0.00431304851888186 -DC.L,DIXONS CARPHONE,462.10�13:11,,756906,0.00363811584680332 -DGE.L,Diageo PLC,"1,881.50�13:13",�6.50�(0.34%),756906,0.00363811584680332 -DLG.L,Direct Line Insurance Group PLC,403.80�13:13,�0.40�(0.10%),1095340,0.00526481995338596 -EXPN.L,Experian PLC,"1,191.00�13:12",�2.00�(0.17%),467283,0.00224602485281105 -EZJ.L,easyJet PLC,"1,682.00�13:12",�28.00�(1.64%),1191230,0.00572572121265722 -FRES.L,Fresnillo PLC,678.50�13:12,�6.50�(0.97%),381871,0.00183548675335462 -GFS.L,G4S PLC,232.30�13:03,�2.00�(0.85%),1096551,0.00527064070033535 -GKN.L,GKN PLC,294.80�13:12,�2.50�(0.86%),792247,0.00380798456516713 -GLEN.L,Glencore PLC,90.48�13:13,�1.65�(1.86%),41631528,0.200104533116974 -GSK.L,GlaxoSmithKline PLC,"1,345.00�13:13",�0.50�(0.04%),1767356,0.00849490672625522 -HIK.L,Hikma Pharmaceuticals PLC,"2,010.00�13:04",�57.00�(2.92%),261511,0.00125696891451962 -HL.L,Hargreaves Lansdown PLC,"1,488.03�13:12",�9.97�(0.67%),372261,0.00178929568961912 -HMSO.L,Hammerson PLC,597.50�13:11,�3.50�(0.58%),478301,0.0022989835562697 -HSBA.L,HSBC Holdings PLC,519.70�13:13,�0.50�(0.10%),7415629,0.0356436828072631 -IAG.L,International Consolidated Airlines Group SA,575.40�13:12,�16.10�(2.72%),4311514,0.0207235606629018 -IHG.L,InterContinental Hotels Group PLC,"2,481.00�13:12",�19.00�(0.76%),219918,0.00105704956863507 -III.L,3i Group PLC,487.30�13:11,�4.50�(0.92%),189987,0.000913184352332553 -IMT.L,Imperial Tobacco Group PLC,"3,571.00�13:13",�29.00�(0.81%),926816,0.00445479884777089 -INTU.L,intu properties plc,319.90�13:09,�4.60�(1.42%),514821,0.0024745192115892 -ISAT.L,Inmarsat PLC,"1,054.44�13:13",�3.44�(0.33%),988089,0.00474931133978598 -ITRK.L,Intertek Group PLC,"2,643.00�13:14",�3.00�(0.11%),45868,0.000220467399731505 -ITV.L,ITV PLC,267.30�13:14,�2.60�(0.96%),3453208,0.0165980593985356 -JMAT.L,Johnson Matthey PLC,"2,445.00�13:14",�29.00�(1.20%),276397,0.00132851940096775 -KGF.L,Kingfisher PLC,346.20�13:14,�4.30�(1.23%),1021408,0.00490946118917235 -LAND.L,Land Securities Group PLC,"1,239.00�13:13",�7.00�(0.56%),384973,0.00185039670961971 -LGEN.L,Legal & General Group PLC,266.00�13:14,�1.60�(0.60%),1998399,0.00960542930051541 -LLOY.L,Lloyds Banking Group PLC,73.86�13:14,�0.02�(0.03%),18907878,0.0908818936317375 -LSE.L,London Stock Exchange Group PLC,"2,544.00�13:11",�6.00�(0.24%),129657,0.000623204448569543 -MGGT.L,Meggitt PLC,386.00�13:15,�3.20�(0.84%),611044,0.00293702105610748 -MKS.L,Marks & Spencer Group PLC,514.75�13:12,�3.25�(0.63%),920128,0.00442265255908587 -MNDI.L,Mondi PLC,"1,463.00�13:14",�7.00�(0.48%),383546,0.00184353774521278 -MRW.L,Morrison (Wm) Supermarkets PLC,155.20�13:14,,920128,0.00442265255908587 -NG.L,National Grid PLC,926.40�13:14,�1.10�(0.12%),1659592,0.00797693234619361 -NXT.L,Next PLC,"7,765.00�13:11",�95.00�(1.21%),114062,0.000548246109448308 -OML.L,Old Mutual PLC,198.50�13:14,�0.40�(0.20%),2040849,0.00980946787029396 -PRU.L,Prudential PLC,"1,499.50�13:15",�14.00�(0.93%),580870,0.00279198784516525 -PSON.L,Pearson PLC,794.00�13:09,�5.00�(0.63%),1177953,0.00566190448495522 -RB.L,Reckitt Benckiser Group PLC,"6,293.00�13:14",�34.00�(0.54%),281172,0.0013514707359664 -RBS.L,Royal Bank of Scotland Group PLC,313.40�13:14,�2.40�(0.77%),2100058,0.0100940596177149 -RDSA.L,Royal Dutch Shell PLC,"1,636.00�13:14",�18.00�(1.11%),2467461,0.0118600050276642 -RDSB.L,Royal Dutch Shell PLC,"1,652.00�13:15",�14.50�(0.89%),1457434,0.0070052473240666 -REL.L,Reed Elsevier PLC,"1,170.00�13:14",0.00�(0.00%),908802,0.00436821343443777 -RIO.L,Rio Tinto PLC,"2,235.00�13:15",�21.00�(0.95%),2190722,0.0105298417823887 -RMG.L,Royal Mail PLC,453.50�13:14,�1.20�(0.26%),995316,0.00478404836555252 -RR.L,Rolls-Royce Group PLC,546.63�13:14,�8.38�(1.51%),2792915,0.0134243199555489 -RRS.L,Randgold Resources Ltd,"3,929.00�13:14",0.00�(0.00%),135524,0.000651404549603483 -RSA.L,RSA Insurance Group PLC,437.10�13:14,�0.10�(0.02%),395477,0.00190088484005443 -SAB.L,SABMiller PLC,"4,011.00�13:15",�1.00�(0.02%),892451,0.00428962133421518 -SBRY.L,Sainsbury (J) PLC,255.80�13:14,�7.40�(2.98%),2395670,0.0115149371133421 -SDR.L,Schroders PLC,"2,930.00�13:09",�12.00�(0.41%),44674,0.000214728364341268 -SGE.L,Sage Group (The) PLC,545.50�13:13,�0.50�(0.09%),539717,0.00259418338669419 -SHP.L,Shire PLC,"4,685.00�13:14",�22.00�(0.47%),221318,0.0010637787558598 -SKY.L,SKY,"1,095.00�13:12",�4.00�(0.37%),925016,0.0044461470356248 -SL.L,Standard Life PLC,399.90�13:14,�3.20�(0.79%),861636,0.00414150711683647 -SMIN.L,Smiths Group PLC,992.50�13:14,�27.50�(2.70%),640309,0.00307768510191594 -SN.L,Smith & Nephew PLC,"1,110.00�13:14",�9.00�(0.82%),480018,0.00230723642374461 -SPD.L,Sports Direct International PLC,694.50�13:11,�1.50�(0.22%),157981,0.000759345519250522 -SSE.L,SSE PLC,"1,463.00�13:13",�2.00�(0.14%),562454,0.00270347019378617 -STAN.L,Standard Chartered PLC,583.00�13:14,�0.60�(0.10%),2018697,0.00970299290214945 -STJ.L,St James's Place PLC,964.00�13:14,�11.00�(1.13%),418480,0.00201145019271912 -SVT.L,Severn Trent PLC,"2,199.00�13:12",�1.00�(0.05%),95342,0.000458267263129005 -TPK.L,Travis Perkins PLC,"1,945.00�13:13",�4.00�(0.21%),92916,0.000446606542981001 -TSCO.L,Tesco PLC,171.54�13:14,�2.54�(1.50%),9831136,0.0472539676970174 -TUI.L,TUI AG,"1,115.00�13:10",�5.00�(0.45%),458970,0.00220606790038304 -TW.L,Taylor Wimpey PLC,183.90�13:15,�1.10�(0.59%),3180729,0.0152883721086725 -ULVR.L,Unilever PLC,"2,791.00�13:14",�29.00�(1.03%),824827,0.0039645823650113 -UU.L,United Utilities Group PLC,959.00�13:10,�2.50�(0.26%),436911,0.00210003994253274 -VOD.L,Vodafone Group PLC,224.25�13:15,�1.30�(0.58%),17572036,0.0844610858312637 -WOS.L,Wolseley PLC,"3,657.00�13:14",�4.00�(0.11%),179536,0.000862950969699912 -WPP.L,WPP PLC,"1,502.00�13:15",�12.00�(0.79%),857887,0.0041234873147611 -WTB.L,Whitbread PLC,"4,484.00�13:16",�60.00�(1.32%),141036,0.000677898321019722 -,,,,208048900, diff --git a/example/basket/src/main/resources/static/hsi.csv b/example/basket/src/main/resources/static/hsi.csv deleted file mode 100644 index fcd24d46c..000000000 --- a/example/basket/src/main/resources/static/hsi.csv +++ /dev/null @@ -1,81 +0,0 @@ -Name,Symbol,Last,Change,Change %,Volume,Turn.,P/E,P/B,Yield,Market Cap,Weighting -CKH HOLDINGS,00001.HK,41.9,1.15,+2.822%,5.15M,215.13M,4.38,0.31,6.98%,160.48B,0.0278736825813547 -CLP HOLDINGS,00002.HK,57.95,-0.1,-0.172%,3.32M,193.19M,156.62,1.39,5.35%,146.41B,0.000417248060431947 -HK & CHINA GAS,00003.HK,5.46,0.13,+2.439%,16.16M,88.00M,19.43,1.66,6.41%,101.88B,0.000417248060431947 -HSBC HOLDINGS,00005.HK,61.7,1.1,+1.815%,22.19M,1.37B,10.54,0.86,4.05%,1,0.00387831899135251 -POWER ASSETS,00006.HK,37.9,-0.25,-0.655%,4.23M,160.75M,14.3,0.93,7.44%,80.77B,0.00159219779580666 -HANG SENG BANK,00011.HK,97.45,2.95,+3.122%,2.54M,247.44M,19.69,1.01,4.21%,186.31B,0.00843059492263598 -HENDERSON LAND,00012.HK,20.65,0.85,+4.293%,5.07M,103.70M,10.81,0.31,8.72%,99.97B,0.00228757277736148 -SHK PPT,00016.HK,83.8,3.25,+4.035%,8.25M,685.41M,10.16,0.4,5.91%,242.83B,0.0107034211668507 -NEW WORLD DEV,00017.HK,15.24,0.8,+5.540%,12.95M,196.19M,30.48,0.18,13.52%,38.35B,0.00391798755004232 -GALAXY ENT,00027.HK,47.15,1.9,+4.199%,11.97M,560.21M,No Profit,3.22,0.00%,206.21B,0.00980506986578636 -MTR CORPORATION,00066.HK,31,0.8,+2.649%,4.68M,144.86M,19.5,1.07,4.23%,192.64B,0.00100752275066102 -HANG LUNG PPT,00101.HK,10.72,0.56,+5.512%,7.68M,81.99M,12.61,0.36,7.28%,48.23B,0.0316063387021032 -GEELY AUTO,00175.HK,9.24,0.17,+1.874%,18.77M,173.30M,16.06,1.15,2.27%,92.99B,0.0022355801929258 -ALI HEALTH,00241.HK,4.88,0.47,+10.658%,53.62M,257.82M,108.09,3.81,0.00%,66.04B,0.00501980543997108 -CITIC,00267.HK,7.2,0.2,+2.857%,11.54M,82.96M,2.78,0.28,9.04%,209.45B,0.00724508516988073 -WH GROUP,00288.HK,4.11,0.08,+1.985%,18.94M,77.65M,4.93,0.7,7.30%,52.73B,0.000456964684744788 -CHINA RES BEER,00291.HK,42.95,1.2,+2.874%,4.83M,207.98M,28.41,4.57,1.41%,139.34B,0.00866405926683583 -OOIL,00316.HK,104.5,-0.4,-0.381%,296.54K,30.98M,0.89,0.66,78.90%,69.01B,0.0237794431982097 -TINGYI,00322.HK,10.94,0.18,+1.673%,2.91M,31.81M,20.75,4.09,9.39%,61.64B,0.000502482829757812 -SINOPEC CORP,00386.HK,4.28,-0.01,-0.233%,92.43M,396.61M,6.94,0.58,9.36%,105.92B,0.0504379547308349 -HKEX,00388.HK,292.6,9,+3.173%,4.61M,1.34B,36.76,7.46,2.44%,370.97B,0.00142104572530785 -TECHTRONIC IND,00669.HK,76,1.35,+1.808%,5.47M,414.78M,16.54,3.43,2.43%,139.45B,0.0188176048996174 -CHINA OVERSEAS,00688.HK,16.24,0.52,+3.308%,13.15M,212.60M,6.76,0.44,4.93%,177.74B,0.000414599644602783 -TENCENT,00700.HK,306.2,8.8,+2.959%,11.25M,3.43B,13.74,3.6,0.78%,2,0.0103078651220939 -CHINA UNICOM,00762.HK,5.68,-0.05,-0.873%,9.23M,52.77M,9.16,0.45,5.44%,173.80B,0.00481217156158961 -LINK REIT,00823.HK,38.4,1.45,+3.924%,12.04M,460.96M,5.42,0.52,7.03%,98.38B,0.0011756418803464 -CHINA RES POWER,00836.HK,14.94,0.32,+2.189%,9.91M,147.81M,10.23,0.87,3.92%,71.87B,0.00431304851888186 -PETROCHINA,00857.HK,5.9,0,0.000%,64.23M,380.44M,6.38,0.7,8.08%,124.48B,0.00363811584680332 -XINYI GLASS,00868.HK,10.14,0.17,+1.705%,3.75M,38.02M,8.01,1.3,6.11%,42.22B,0.00363811584680332 -ZHONGSHENG HLDG,00881.HK,22.05,1.45,+7.039%,6.76M,147.71M,7.08,1.07,4.94%,52.72B,0.00526481995338596 -CNOOC,00883.HK,13.78,-0.02,-0.145%,26.37M,365.08M,4.03,0.97,19.09%,655.47B,0.00224602485281105 -CCB,00939.HK,4.42,0.06,+1.376%,233.61M,1.03B,3.06,0.35,9.93%,1,0.00572572121265722 -CHINA MOBILE,00941.HK,65.7,0.25,+0.382%,7.82M,516.10M,9.91,0.96,6.71%,1,0.00183548675335462 -LONGFOR GROUP,00960.HK,14.08,0.9,+6.829%,10.88M,150.68M,3.06,0.55,9.05%,92.81B,0.00527064070033535 -XINYI SOLAR,00968.HK,5.86,0.28,+5.018%,15.99M,92.88M,13.64,1.75,3.41%,52.17B,0.00380798456516713 -SMIC,00981.HK,20.05,0.25,+1.263%,13.10M,264.32M,11.17,1.06,0.00%,159.31B,0.200104533116974 -LENOVO GROUP,00992.HK,8.07,0.25,+3.197%,33.60M,270.50M,7.61,2.23,4.71%,97.87B,0.00849490672625522 -CKI HOLDINGS,01038.HK,37.05,-0.2,-0.537%,1.44M,53.73M,12.03,0.78,6.83%,93.35B,0.00125696891451962 -HENGAN INT'L,01044.HK,24.95,0.2,+0.808%,2.62M,64.97M,13.35,1.32,6.33%,28.99B,0.00178929568961912 -CHINA SHENHUA,01088.HK,25.4,0.35,+1.397%,7.98M,203.11M,6.14,1.13,11.33%,85.79B,0.0022989835562697 -CSPC PHARMA,01093.HK,5.74,0.05,+0.879%,29.29M,167.41M,9.96,2.01,3.66%,68.32B,0.0356436828072631 -SINOPHARM,01099.HK,22.7,0.2,+0.889%,2.07M,46.80M,7.37,0.92,4.08%,30.46B,0.0207235606629018 -CHINA RES LAND,01109.HK,31.2,1,+3.311%,9.88M,305.88M,7.02,0.81,5.07%,222.49B,0.00105704956863507 -CK ASSET,01113.HK,41.25,1.25,+3.125%,8.57M,352.44M,6.9,0.39,5.53%,146.47B,0.000913184352332553 -SINO BIOPHARM,01177.HK,2.83,0.02,+0.712%,26.30M,74.09M,18.37,1.59,4.24%,53.21B,0.00445479884777089 -CHINA RES MIXC,01209.HK,31.6,1.6,+5.333%,3.07M,96.42M,28.97,4.48,2.87%,72.13B,0.0024745192115892 -BYD COMPANY,01211.HK,242,7,+2.979%,3.90M,938.50M,37.57,5.63,0.53%,265.72B,0.00474931133978598 -AIA,01299.HK,63.85,0.95,+1.510%,38.75M,2.48B,408.88,2.53,2.41%,735.40B,0.000220467399731505 -CHINAHONGQIAO,01378.HK,7.67,0.28,+3.789%,13.05M,99.58M,7.27,0.76,6.65%,72.68B,0.0165980593985356 -ICBC,01398.HK,3.77,0.07,+1.892%,233.48M,881.67M,3.45,0.36,9.08%,327.21B,0.00132851940096775 -XIAOMI-W,01810.HK,12.34,0.62,+5.290%,78.53M,960.98M,109.39,1.9,0.00%,308.83B,0.00490946118917235 -BUD APAC,01876.HK,15.46,0.16,+1.046%,16.17M,250.45M,28.65,2.44,1.91%,204.74B,0.00185039670961971 -SANDS CHINA LTD,01928.HK,24,0.95,+4.121%,19.98M,475.93M,No Profit,N/A,0.00%,194.24B,0.00960542930051541 -CHOW TAI FOOK,01929.HK,11.8,0.28,+2.431%,4.88M,57.68M,21.93,3.64,10.34%,118.00B,0.0908818936317375 -WHARF REIC,01997.HK,30.25,1.4,+4.853%,4.23M,127.31M,No Profit,0.48,4.33%,91.85B,0.000623204448569543 -ANTA SPORTS,02020.HK,88.15,4.4,+5.254%,4.82M,422.51M,27.71,6.16,1.52%,249.70B,0.00293702105610748 -WUXI BIO,02269.HK,45.65,1.55,+3.515%,17.91M,811.49M,38.18,4.88,0.00%,194.01B,0.00442265255908587 -SHENZHOU INTL,02313.HK,75,4.6,+6.534%,5.52M,410.68M,21.87,3.25,2.55%,112.74B,0.00184353774521278 -PING AN,02318.HK,44.85,0.85,+1.932%,23.05M,1.03B,8.28,0.85,6.09%,334.02B,0.00442265255908587 -MENGNIU DAIRY,02319.HK,26.25,1.5,+6.061%,8.58M,223.15M,17.34,2.3,1.73%,103.42B,0.00797693234619361 -LI NING,02331.HK,32.95,1.5,+4.769%,22.54M,738.37M,18.8,3.16,1.58%,86.86B,0.000548246109448308 -SUNNY OPTICAL,02382.HK,54.7,1.05,+1.957%,5.62M,308.60M,22.01,2.44,0.91%,60.00B,0.00980946787029396 -BOC HONG KONG,02388.HK,21.45,0.3,+1.418%,6.53M,140.32M,8.38,0.75,6.33%,226.79B,0.00279198784516525 -CHINA LIFE,02628.HK,12.2,0.24,+2.007%,13.53M,165.07M,9.49,0.7,4.53%,90.78B,0.00566190448495522 -ENN ENERGY,02688.HK,65,1.15,+1.801%,3.06M,198.69M,11.08,1.67,4.48%,73.53B,0.0013514707359664 -ZIJIN MINING,02899.HK,11.98,0.16,+1.354%,16.20M,194.50M,13.97,3.14,1.88%,68.73B,0.0100940596177149 -MEITUAN-W,03690.HK,114.6,3.8,+3.430%,19.17M,2.19B,No Profit,4.89,0.00%,715.43B,0.0118600050276642 -HANSOH PHARMA,03692.HK,10.66,0.16,+1.524%,17.56M,187.72M,21.48,2.47,0.94%,63.25B,0.0070052473240666 -CM BANK,03968.HK,32.7,0.1,+0.307%,11.13M,363.99M,5.51,0.86,6.00%,150.12B,0.00436821343443777 -BANK OF CHINA,03988.HK,2.74,0.05,+1.859%,275.47M,754.54M,3.33,0.33,9.55%,229.13B,0.0105298417823887 -CG SERVICES,06098.HK,8.08,0.25,+3.193%,16.08M,128.87M,12.42,0.65,5.20%,27.01B,0.00478404836555252 -JD HEALTH,06618.HK,40.6,2.95,+7.835%,7.75M,312.36M,299.91,2.56,0.00%,129.12B,0.0134243199555489 -HAIER SMARTHOME,06690.HK,24.65,1.15,+4.894%,7.24M,178.37M,13.83,2.21,2.59%,70.46B,0.000651404549603483 -HAIDILAO,06862.HK,21,0.6,+2.941%,6.86M,143.79M,74.46,13.94,0.55%,117.05B,0.00190088484005443 -JD-SW,09618.HK,115.1,4,+3.600%,7.43M,852.28M,30.73,1.5,6.38%,360.24B,0.00428962133421518 -NONGFU SPRING,09633.HK,45,1.5,+3.448%,3.69M,165.62M,52.49,18.63,1.71%,226.56B,0.0115149371133421 -BIDU-SW,09888.HK,133.4,4.6,+3.571%,5.82M,772.73M,47.3,1.5,0.00%,377.37B,0.000214728364341268 -TRIP.COM-S,09961.HK,279.2,7,+2.572%,1.25M,349.59M,114.05,1.4,0.00%,176.65B,0.00259418338669419 -BABA-SW,09988.HK,85.6,2.6,+3.133%,34.61M,2.96B,21.65,1.62,0.00%,1,0.0010637787558598 -NTES-S,09999.HK,159.5,8.3,+5.489%,5.02M,797.10M,22.7,4.63,1.36%,546.99B,0.0044461470356248 diff --git a/example/basket/src/main/resources/static/nasdaq100.csv b/example/basket/src/main/resources/static/nasdaq100.csv deleted file mode 100644 index 6447cbb7a..000000000 --- a/example/basket/src/main/resources/static/nasdaq100.csv +++ /dev/null @@ -1,102 +0,0 @@ -#,Name,Symbol,Weighting,Last Trade,Chg,% Chg -1,Apple Inc,AAPL,11.007,174.94,0.15,(0.09%) -2,Microsoft Corp,MSFT,9.61,316.98,-0.03,(-0.01%) -3,Amazon.com Inc,AMZN,5.401,129.31,0.19,(0.14%) -4,NVIDIA Corp,NVDA,4.101,415.74,-0.36,(-0.09%) -5,Meta Platforms Inc,META,3.729,299.42,0.34,(0.11%) -6,Tesla Inc,TSLA,3.285,244.13,-0.75,(-0.31%) -7,Alphabet Inc,GOOGL,3.133,130.49,0.24,(0.18%) -8,Alphabet Inc,GOOG,3.085,131.49,0.24,(0.18%) -9,Broadcom Inc,AVGO,2.896,833.04,3.96,(0.48%) -10,Costco Wholesale Corp,COST,2.137,557.85,-0.74,(-0.13%) -11,PepsiCo Inc,PEP,2.096,174.84,-0.43,(-0.25%) -12,Adobe Inc,ADBE,2.033,511.42,-1.48,(-0.29%) -13,Cisco Systems Inc,CSCO,1.887,53.68,0.11,(0.20%) -14,Comcast Corp,CMCSA,1.633,45.30,-0.01,(-0.01%) -15,Netflix Inc,NFLX,1.478,379.89,0.08,(0.02%) -16,T-Mobile US Inc,TMUS,1.43,140.18,0.83,(0.60%) -17,Advanced Micro Devices Inc,AMD,1.348,96.09,-0.11,(-0.12%) -18,Texas Instruments Inc,TXN,1.264,161.00,0.69,(0.43%) -19,Intel Corp,INTC,1.26,34.19,0.01,(0.01%) -20,Amgen Inc,AMGN,1.251,271.18,3.48,(1.30%) -21,Intuit Inc,INTU,1.226,509.00,0.43,(0.08%) -22,Honeywell International Inc,HON,1.103,188.67,-1.12,(-0.59%) -23,QUALCOMM Inc,QCOM,1.046,107.53,-0.16,(-0.14%) -24,Applied Materials Inc,AMAT,0.982,136.32,0.15,(0.11%) -25,Booking Holdings Inc,BKNG,0.941,3,019.20,-43.30,(-1.42%) -26,Starbucks Corp,SBUX,0.926,93.80,0.12,(0.12%) -27,Intuitive Surgical Inc,ISRG,0.867,288.50,0.30,(0.10%) -28,Automatic Data Processing Inc,ADP,0.854,239.45,0.10,(0.04%) -29,Mondelez International Inc,MDLZ,0.835,71.25,0.82,(1.16%) -30,Gilead Sciences Inc,GILD,0.814,75.47,0.46,(0.61%) -31,Vertex Pharmaceuticals Inc,VRTX,0.794,353.67,4.14,(1.18%) -32,Regeneron Pharmaceuticals Inc,REGN,0.763,828.09,3.25,(0.39%) -33,Analog Devices Inc,ADI,0.752,176.82,1.34,(0.76%) -34,Lam Research Corp,LRCX,0.702,620.00,0.89,(0.14%) -35,Micron Technology Inc,MU,0.646,68.90,0.02,(0.03%) -36,Palo Alto Networks Inc,PANW,0.604,228.70,0.19,(0.08%) -37,Synopsys Inc,SNPS,0.587,447.12,0.27,(0.06%) -38,Charter Communications Inc,CHTR,0.581,441.88,-3.33,(-0.75%) -39,MercadoLibre Inc,MELI,0.562,1,275.50,-1.47,(-0.11%) -40,PayPal Holdings Inc,PYPL,0.559,57.90,0.02,(0.03%) -41,CSX Corp,CSX,0.54,31.23,0.03,(0.09%) -42,Cadence Design Systems Inc,CDNS,0.539,230.83,0.17,(0.07%) -43,KLA Corp,KLAC,0.53,456.11,4.29,(0.95%) -44,PDD Holdings Inc ADR,PDD,0.521,95.93,-0.01,(-0.01%) -45,Marriott International Inc/MD,MAR,0.505,193.90,-0.46,(-0.23%) -46,Monster Beverage Corp,MNST,0.498,54.48,-0.04,(-0.08%) -47,Airbnb Inc,ABNB,0.491,132.09,-0.11,(-0.08%) -48,O'Reilly Automotive Inc,ORLY,0.485,936.67,0.65,(0.07%) -49,Cintas Corp,CTAS,0.446,505.27,0.52,(0.10%) -50,ASML Holding NV,ASML,0.438,585.00,-2.10,(-0.36%) -51,NXP Semiconductors NV,NXPI,0.434,196.76,-0.04,(-0.02%) -52,Workday Inc,WDAY,0.414,235.55,4.73,(2.05%) -53,Lululemon Athletica Inc,LULU,0.405,386.36,-1.69,(-0.44%) -54,Keurig Dr Pepper Inc,KDP,0.404,33.25,0.13,(0.39%) -55,Fortinet Inc,FTNT,0.401,58.29,0.05,(0.09%) -56,Marvell Technology Inc,MRVL,0.388,52.38,0.08,(0.14%) -57,PACCAR Inc,PCAR,0.38,84.97,0.04,(0.04%) -58,Old Dominion Freight Line Inc,ODFL,0.38,401.01,0.35,(0.09%) -59,Autodesk Inc,ADSK,0.379,204.07,0.03,(0.01%) -60,Kraft Heinz Co/The,KHC,0.368,34.27,0.11,(0.31%) -61,Microchip Technology Inc,MCHP,0.36,77.00,-0.08,(-0.10%) -62,Copart Inc,CPRT,0.358,43.26,0.10,(0.22%) -63,American Electric Power Co Inc,AEP,0.357,79.23,0.06,(0.08%) -64,Paychex Inc,PAYX,0.355,113.01,0.06,(0.06%) -65,Exelon Corp,EXC,0.35,40.28,0.07,(0.16%) -66,ON Semiconductor Corp,ON,0.341,93.87,0.06,(0.06%) -67,AstraZeneca PLC ADR,AZN,0.339,67.35,-0.49,(-0.72%) -68,Seagen Inc,SGEN,0.336,212.18,-1.52,(-0.71%) -69,Ross Stores Inc,ROST,0.335,111.71,0.05,(0.04%) -70,Moderna Inc,MRNA,0.331,100.32,0.33,(0.33%) -71,Biogen Inc,BIIB,0.326,257.93,0.25,(0.10%) -72,Crowdstrike Holdings Inc,CRWD,0.319,162.85,0.28,(0.17%) -73,IDEXX Laboratories Inc,IDXX,0.316,439.41,3.72,(0.85%) -74,Baker Hughes Co,BKR,0.307,35.44,0.04,(0.10%) -75,Constellation Energy Corp,CEG,0.307,110.41,0.05,(0.04%) -76,Cognizant Technology Solutions Corp,CTSH,0.303,70.19,0.58,(0.83%) -77,Verisk Analytics Inc,VRSK,0.303,242.05,0.10,(0.04%) -78,Dexcom Inc,DXCM,0.3,88.30,0.80,(0.92%) -79,Trade Desk Inc/The,TTD,0.293,76.38,0.03,(0.03%) -80,Xcel Energy Inc,XEL,0.284,59.76,0.03,(0.04%) -81,Electronic Arts Inc,EA,0.279,118.38,-0.63,(-0.53%) -82,CoStar Group Inc,CSGP,0.277,78.18,0.12,(0.15%) -83,GLOBALFOUNDRIES Inc,GFS,0.273,57.21,0.38,(0.67%) -84,Fastenal Co,FAST,0.268,54.32,0.11,(0.20%) -85,Atlassian Corp,TEAM,0.253,196.01,0.55,(0.28%) -86,GE HealthCare Technologies Inc,GEHC,0.252,63.78,-0.56,(-0.86%) -87,Warner Bros Discovery Inc,WBD,0.244,11.09,-0.02,(-0.14%) -88,Diamondback Energy Inc,FANG,0.235,150.70,0.13,(0.09%) -89,Datadog Inc,DDOG,0.23,88.81,0.05,(0.06%) -90,ANSYS Inc,ANSS,0.227,300.60,-2.31,(-0.76%) -91,eBay Inc,EBAY,0.203,43.22,0.09,(0.20%) -92,Dollar Tree Inc,DLTR,0.201,104.77,0.27,(0.25%) -93,Align Technology Inc,ALGN,0.2,297.25,-1.31,(-0.44%) -94,Zscaler Inc,ZS,0.188,151.80,0.09,(0.06%) -95,Illumina Inc,ILMN,0.183,132.31,-0.13,(-0.10%) -96,Walgreens Boots Alliance Inc,WBA,0.161,21.18,0.06,(0.28%) -97,Zoom Video Communications Inc,ZM,0.151,68.57,-0.29,(-0.41%) -98,Enphase Energy Inc,ENPH,0.148,120.41,0.49,(0.41%) -99,Sirius XM Holdings Inc,SIRI,0.137,4.05,0.02,(0.50%) -100,JD.com Inc ADR,JD,0.117,30.43,0.02,(0.05%) -101,Lucid Group Inc,LCID,0.102,5.14,0.03,(0.49%) \ No newline at end of file diff --git a/example/basket/src/main/resources/static/sp500.csv b/example/basket/src/main/resources/static/sp500.csv deleted file mode 100644 index 19701b2cc..000000000 --- a/example/basket/src/main/resources/static/sp500.csv +++ /dev/null @@ -1,504 +0,0 @@ -#,Name,Symbol,Weighting,Price,Change,Change %, -1,Apple Inc,AAPL,6.992488,171.9,1.47,(0.86%), -2,Microsoft Corp,MSFT,6.487978,314.55,1.76,(0.56%), -3,Amazon.com Inc,AMZN,3.193379,126.25,0.27,(0.22%), -4,Nvidia Corp,NVDA,2.928461,433.11,8.43,(1.99%), -5,Alphabet Inc Cl A,GOOGL,2.162218,132.93,2.39,(1.83%), -6,Tesla Inc,TSLA,1.854311,246.56,6.06,(2.52%), -7,Alphabet Inc Cl C,GOOG,1.85251,133.81,2.35,(1.78%), -8,Meta Platforms Inc Class A,META,1.847731,305.93,8.19,(2.75%), -9,Berkshire Hathaway Inc Cl B,BRK.B,1.82184,358.67,0.89,(0.25%), -10,Exxon Mobil Corp,XOM,1.343563,118.97,-1.23,(-1.03%), -11,Unitedhealth Group Inc,UNH,1.302884,510.04,6.31,(1.25%), -12,Eli Lilly & Co,LLY,1.224046,546.65,-3.11,(-0.57%), -13,Jpmorgan Chase & Co,JPM,1.182918,148.23,2.45,(1.68%), -14,Johnson & Johnson W/d,JNJ,1.056344,156.83,-0.28,(-0.18%), -15,Visa Inc Class a Shares,V,1.029636,231.97,2.47,(1.08%), -16,Procter & Gamble Co,PG,0.969793,145.75,-1.59,(-1.08%), -17,Broadcom Inc,AVGO,0.941177,835.33,18.52,(2.27%), -18,Mastercard Inc A,MA,0.918779,400.65,5.17,(1.31%), -19,Chevron Corp,CVX,0.847353,170.55,-0.49,(-0.28%), -20,Home Depot Inc,HD,0.847289,304.35,2.53,(0.84%), -22,Abbvie Inc,ABBV,0.754672,152.14,-0.99,(-0.65%), -23,Merck & Co. Inc.,MRK,0.736434,104.2,0.26,(0.25%), -24,Costco Wholesale Corp,COST,0.697258,569.05,5.52,(0.98%), -25,Pepsico Inc,PEP,0.651768,168.92,-0.65,(-0.38%), -26,Walmart Inc,WMT,0.644449,161.87,0.15,(0.09%), -27,Adobe Inc,ADBE,0.639652,507.17,4.57,(0.91%), -28,Coca Cola Co,KO,0.60801,55.82,-0.13,(-0.23%), -29,Cisco Systems Inc,CSCO,0.605326,53.97,0.77,(1.44%), -30,Accenture Plc Cl A,ACN,0.55372,298.5,-15.9,(-5.05%), -31,Salesforce Inc,CRM,0.551342,204.46,1.73,(0.85%), -32,Thermo Fisher Scientific Inc,TMO,0.536951,503.47,5.18,(1.04%), -33,Mcdonald S Corp,MCD,0.536457,265.83,2.19,(0.83%), -34,Bank of America Corp,BAC,0.526405,27.51,0.24,(0.86%), -35,Comcast Corp Class A,CMCSA,0.512537,45.17,0.57,(1.27%), -36,Linde Plc,LIN,0.506835,375.48,3.47,(0.93%), -37,Pfizer Inc,PFE,0.506043,32.09,-0.02,(-0.05%), -38,Netflix Inc,NFLX,0.467192,377.77,0.18,(0.05%), -39,Abbott Laboratories,ABT,0.462893,97.52,1.99,(2.08%), -40,Oracle Corp,ORCL,0.459877,106.29,1.67,(1.60%), -41,Danaher Corp,DHR,0.454026,248.24,0.8,(0.32%), -42,Advanced Micro Devices,AMD,0.442473,103.74,5.67,(5.78%), -43,Wells Fargo & Co,WFC,0.417428,41.04,0.18,(0.43%), -44,Conocophillips,COP,0.411569,123.32,0.23,(0.18%), -45,Walt Disney Co,DIS,0.408438,80.35,0.45,(0.56%), -46,Intel Corp,INTC,0.404462,35.5,0.89,(2.56%), -47,Amgen Inc,AMGN,0.401904,270.91,1.93,(0.72%), -48,Texas Instruments Inc,TXN,0.400931,160.98,2.84,(1.80%), -49,Intuit Inc,INTU,0.397406,515.11,6.87,(1.35%), -50,Philip Morris International,PM,0.39143,92.66,2.34,(2.59%), -51,Caterpillar Inc,CAT,0.388444,276.34,3.63,(1.33%), -52,Verizon Communications Inc,VZ,0.380327,32.56,0.16,(0.48%), -53,Intl Business Machines Corp,IBM,0.364246,140.89,-2.28,(-1.59%), -54,Honeywell International Inc,HON,0.348317,188.68,0.8,(0.43%), -55,Union Pacific Corp,UNP,0.344419,203.88,1.48,(0.73%), -56,Qualcomm Inc,QCOM,0.340195,111.55,2.36,(2.16%), -57,Nextera Energy Inc,NEE,0.338809,57.64,-2.32,(-3.88%), -58,Lowe S Cos Inc,LOW,0.338613,209.52,2.56,(1.24%), -59,Bristol Myers Squibb Co,BMY,0.337683,58.3,0.41,(0.70%), -60,General Electric Co,GE,0.336989,112.43,1.54,(1.39%), -61,S&p Global Inc,SPGI,0.32985,369.21,6.15,(1.69%), -62,Applied Materials Inc,AMAT,0.316678,139.15,4.09,(3.03%), -63,Servicenow Inc,NOW,0.3112,552.84,6.46,(1.18%), -64,Boeing Co,BA,0.309673,193.12,-2.34,(-1.20%), -65,United Parcel Service Cl B,UPS,0.307795,154.29,1.88,(1.23%), -66,Booking Holdings Inc,BKNG,0.307126,3,86.26,3.6,(0.12%) -67,Nike Inc Cl B,NKE,0.305871,89.63,0.21,(0.24%), -68,At&t Inc,T,0.296603,14.94,0.07,(0.44%), -69,Goldman Sachs Group Inc,GS,0.296356,325.72,3.77,(1.17%), -70,Rtx Corp,RTX,0.296189,72.54,-0.34,(-0.46%), -71,Elevance Health Inc,ELV,0.292632,448.99,4.23,(0.95%), -72,Deere & Co,DE,0.291602,388.36,4,(1.04%), -73,Starbucks Corp,SBUX,0.291579,91.21,0.04,(0.04%), -74,Morgan Stanley,MS,0.29087,82.34,0.69,(0.84%), -75,Medtronic Plc,MDT,0.290688,78.77,0.55,(0.71%), -76,Prologis Inc,PLD,0.286912,112.3,1.05,(0.94%), -77,Intuitive Surgical Inc,ISRG,0.285764,296.31,4.88,(1.67%), -78,Tjx Companies Inc,TJX,0.282733,89.27,1.16,(1.32%), -79,Automatic Data Processing,ADP,0.279113,243.79,1.16,(0.48%), -80,Marsh & Mclennan Cos,MMC,0.266169,193.53,0.55,(0.29%), -81,Mondelez International Inc A,MDLZ,0.26425,69.44,-0.56,(-0.79%), -82,Gilead Sciences Inc,GILD,0.26285,75.96,0.41,(0.54%), -83,Lockheed Martin Corp,LMT,0.255775,410.4,1.68,(0.41%), -84,Blackrock Inc,BLK,0.252096,645.37,1.98,(0.31%), -85,Vertex Pharmaceuticals Inc,VRTX,0.251521,353.91,4.26,(1.22%), -86,Stryker Corp,SYK,0.250789,273.07,6.53,(2.45%), -87,Cvs Health Corp,CVS,0.250255,70.11,0.33,(0.47%), -88,Regeneron Pharmaceuticals,REGN,0.2481,835.67,3.11,(0.37%), -89,American Express Co,AXP,0.243515,150.42,0.52,(0.34%), -90,Chubb Ltd,CB,0.242706,212.92,1.29,(0.61%), -91,Analog Devices Inc,ADI,0.241943,177.01,4.2,(2.43%), -92,Schlumberger Ltd,SLB,0.241232,61.02,0.22,(0.36%), -93,Eaton Corp Plc,ETN,0.238556,216.42,2.06,(0.96%), -94,The Cigna Group,CI,0.238517,291.43,2.82,(0.98%), -95,Progressive Corp,PGR,0.229854,140.76,0.14,(0.10%), -96,Lam Research Corp,LRCX,0.228483,627.46,13.54,(2.20%), -97,Schwab (Charles) Corp,SCHW,0.225784,54.57,0.19,(0.35%), -98,Zoetis Inc,ZTS,0.224522,174.68,0,(-0.00%), -99,Citigroup Inc,C,0.217552,41.24,0.78,(1.92%), -100,Boston Scientific Corp,BSX,0.213003,53.3,1.2,(2.31%), -101,Blackstone Inc,BX,0.211158,108.88,2.33,(2.19%), -102,Eog Resources Inc,EOG,0.21104,130.56,0.75,(0.57%), -103,Becton Dickinson and Co,BDX,0.209627,262.6,3.8,(1.47%), -104,Micron Technology Inc,MU,0.208276,66.25,-1.96,(-2.87%), -105,American Tower Corp,AMT,0.207727,160.73,1.04,(0.65%), -106,Altria Group Inc,MO,0.207666,42.11,0.2,(0.47%), -107,T Mobile Us Inc,TMUS,0.20192,140.3,0.6,(0.43%), -108,Cme Group Inc,CME,0.201368,200.22,-0.14,(-0.07%), -109,Southern Co,SO,0.20116,65.04,-1.1,(-1.67%), -110,Palo Alto Networks Inc,PANW,0.198047,236.42,4.52,(1.95%), -111,Duke Energy Corp,DUK,0.193827,88.87,-1.23,(-1.36%), -112,Fiserv Inc,FI,0.192662,113.67,0.48,(0.42%), -113,Synopsys Inc,SNPS,0.189768,458.88,12.17,(2.72%), -114,Activision Blizzard Inc,ATVI,0.18717,93.71,-0.22,(-0.23%), -115,Aon Plc Class A,AON,0.186896,330.04,0.12,(0.04%), -116,Equinix Inc,EQIX,0.184757,715.84,8.74,(1.24%), -117,Illinois Tool Works,ITW,0.177501,233.17,0.77,(0.33%), -118,Air Products & Chemicals Inc,APD,0.17678,289.15,3.89,(1.36%), -119,Paypal Holdings Inc,PYPL,0.175802,58.3,0.96,(1.67%), -120,Cadence Design Sys Inc,CDNS,0.175052,235.09,4.44,(1.93%), -121,Northrop Grumman Corp,NOC,0.173654,441.3,4.06,(0.93%), -122,Intercontinental Exchange In,ICE,0.172998,109.93,1.66,(1.53%), -123,Humana Inc,HUM,0.170476,495.73,2.16,(0.44%), -124,Marathon Petroleum Corp,MPC,0.170186,155.28,2.85,(1.87%), -125,Kla Corp,KLAC,0.170079,459.61,14.05,(3.15%), -126,Fedex Corp,FDX,0.169747,266.99,4.28,(1.63%), -127,Csx Corp,CSX,0.169632,30.62,0.34,(1.14%), -128,Mckesson Corp,MCK,0.167376,445.58,1.2,(0.27%), -129,Sherwin Williams Co,SHW,0.165389,254.95,4.33,(1.73%), -130,Colgate Palmolive Co,CL,0.164,71.11,0.06,(0.08%), -131,Airbnb Inc Class A,ABNB,0.159553,137.66,3.63,(2.70%), -132,Waste Management Inc,WM,0.15893,154.17,-0.25,(-0.16%), -133,Emerson Electric Co,EMR,0.154857,97.31,0.45,(0.47%), -134,O Reilly Automotive Inc,ORLY,0.154194,918.15,3.98,(0.44%), -135,Pioneer Natural Resources Co,PXD,0.1524,234.43,0.34,(0.14%), -136,Phillips 66,PSX,0.150197,122.81,2.01,(1.66%), -137,Freeport Mcmoran Inc,FCX,0.146185,37.34,0.79,(2.17%), -138,3m Co W/d,MMM,0.144312,93.48,0.02,(0.02%), -139,Roper Technologies Inc,ROP,0.144165,486.61,-0.02,(-0.00%), -140,Valero Energy Corp,VLO,0.141937,147.59,3.64,(2.53%), -141,Nxp Semiconductors Nv,NXPI,0.141583,202.19,5.49,(2.79%), -142,Target Corp,TGT,0.141106,109.31,-0.44,(-0.40%), -143,Parker Hannifin Corp,PH,0.140358,396.29,5.18,(1.32%), -144,Us Bancorp,USB,0.139291,32.59,0.07,(0.20%), -145,General Dynamics Corp,GD,0.139193,223.44,2.44,(1.10%), -146,Chipotle Mexican Grill Inc,CMG,0.139055,1,828.59,22.51,(1.25%) -147,Hca Healthcare Inc,HCA,0.138966,251.59,4.33,(1.75%), -148,Arthur J Gallagher & Co,AJG,0.138231,231.77,1.44,(0.62%), -149,Moody S Corp,MCO,0.138162,319.07,4.56,(1.45%), -150,Amphenol Corp Cl A,APH,0.136941,84.4,2.04,(2.47%), -151,Ford Motor Co,F,0.1362,12.58,0.19,(1.49%), -152,Marriott International Cl A,MAR,0.135619,199.53,5.65,(2.92%), -153,Pnc Financial Services Group,PNC,0.135457,123.09,1.28,(1.05%), -154,Transdigm Group Inc,TDG,0.131273,860.46,8.64,(1.01%), -155,Carrier Global Corp,CARR,0.129065,56.83,1.75,(3.17%), -156,Autozone Inc,AZO,0.128857,2,556.17,15.27,(0.60%) -157,Trane Technologies Plc,TT,0.12759,207.07,7.01,(3.50%), -158,Motorola Solutions Inc,MSI,0.127284,275.18,2.2,(0.81%), -159,Arista Networks Inc,ANET,0.12715,184.23,2.63,(1.45%), -160,Norfolk Southern Corp,NSC,0.124378,197.3,1.08,(0.55%), -161,General Motors Co,GM,0.124282,33.25,0.9,(2.77%), -162,Paccar Inc,PCAR,0.123613,86.12,1.31,(1.54%), -163,Charter Communications Inc A,CHTR,0.123199,442.28,8.86,(2.04%), -164,Hess Corp,HES,0.121942,157.3,-0.74,(-0.47%), -165,Sempra,SRE,0.121909,68.15,-1.26,(-1.81%), -166,Occidental Petroleum Corp,OXY,0.121531,66.03,0.43,(0.66%), -167,American International Group,AIG,0.121272,61.73,0.72,(1.18%), -168,Autodesk Inc,ADSK,0.120711,208.03,5.75,(2.84%), -169,Edwards Lifesciences Corp,EW,0.119074,69.68,-0.43,(-0.62%), -170,Ecolab Inc,ECL,0.118911,169.5,1.63,(0.97%), -171,Public Storage,PSA,0.117206,266.58,1.6,(0.60%), -172,Microchip Technology Inc,MCHP,0.116275,78.91,2.41,(3.15%), -173,Aflac Inc,AFL,0.11627,77.65,0.62,(0.81%), -174,Cintas Corp,CTAS,0.116227,486.83,5.75,(1.19%), -175,Welltower Inc,WELL,0.116157,81.07,0.87,(1.08%), -176,Williams Cos Inc,WMB,0.115685,34.65,0.55,(1.61%), -177,Kimberly Clark Corp,KMB,0.114902,121.11,-0.55,(-0.45%), -178,Archer Daniels Midland Co,ADM,0.114307,76.74,0.38,(0.50%), -179,Msci Inc,MSCI,0.113047,518.97,7.03,(1.37%), -180,Constellation Brands Inc A,STZ,0.112869,251.62,1.03,(0.41%), -181,On Semiconductor,ON,0.111009,95.12,3.07,(3.33%), -182,Metlife Inc,MET,0.110772,63.06,0.26,(0.41%), -183,Monster Beverage Corp,MNST,0.110311,53.31,0.19,(0.35%), -184,Hilton Worldwide Holdings In,HLT,0.109054,153.24,3.88,(2.60%), -185,American Electric Power,AEP,0.108899,74.71,-1.15,(-1.51%), -186,Crown Castle Inc,CCI,0.108512,91.35,1.65,(1.83%), -187,Exelon Corp,EXC,0.107894,38.11,-0.69,(-1.78%), -188,Nucor Corp,NUE,0.107787,158.31,2.6,(1.67%), -189,Travelers Cos Inc,TRV,0.107342,167.42,-0.51,(-0.30%), -190,Dominion Energy Inc,D,0.106001,44.61,-0.86,(-1.88%), -191,Te Connectivity Ltd,TEL,0.105581,123.84,3.4,(2.82%), -192,Halliburton Co,HAL,0.105449,42.18,0.15,(0.37%), -193,Centene Corp,CNC,0.105443,69.87,0.13,(0.18%), -194,Fortinet Inc,FTNT,0.105315,59.07,0.93,(1.59%), -195,Oneok Inc,OKE,0.104854,64.86,0.35,(0.53%), -196,General Mills Inc,GIS,0.104655,63.79,-0.26,(-0.40%), -197,Copart Inc,CPRT,0.104453,43.66,0.61,(1.41%), -198,Paychex Inc,PAYX,0.104412,117.4,0.89,(0.76%), -199,Biogen Inc,BIIB,0.103916,258.95,1.43,(0.55%), -200,Truist Financial Corp,TFC,0.103679,28.15,0.18,(0.63%), -201,Ross Stores Inc,ROST,0.10361,111.18,2.26,(2.07%), -202,Johnson Controls Internation,JCI,0.103601,53.69,-0.85,(-1.55%), -203,Iqvia Holdings Inc,IQV,0.103397,200.11,-2.1,(-1.04%), -204,Capital One Financial Corp,COF,0.101688,96.63,1.14,(1.20%), -205,Baker Hughes Co,BKR,0.101425,36.62,0.37,(1.02%), -206,Idexx Laboratories Inc,IDXX,0.101263,439.37,2.51,(0.57%), -207,Corteva Inc,CTVA,0.100577,50.77,0.02,(0.05%), -208,Dow Inc,DOW,0.100258,50.87,-0.13,(-0.26%), -209,Old Dominion Freight Line,ODFL,0.100037,406.82,6.93,(1.73%), -210,Constellation Energy,CEG,0.099445,109.94,-0.81,(-0.73%), -211,Dexcom Inc,DXCM,0.099384,95.68,3.59,(3.90%), -212,Simon Property Group Inc,SPG,0.098977,108.45,0.26,(0.24%), -213,Digital Realty Trust Inc,DLR,0.098757,117.6,0.76,(0.65%), -214,Realty Income Corp,O,0.098278,49.83,0.17,(0.33%), -215,Kenvue Inc W/i,KVUE,0.097359,20.2,-0.02,(-0.12%), -216,Verisk Analytics Inc,VRSK,0.097203,241.97,2.34,(0.98%), -217,Cognizant Tech Solutions A,CTSH,0.096172,68.15,-0.05,(-0.07%), -218,P G & E Corp,PCG,0.095995,16.36,-0.09,(-0.52%), -219,Prudential Financial Inc,PRU,0.095804,94.93,0.41,(0.43%), -220,Ametek Inc,AME,0.09567,150.03,1.17,(0.79%), -221,Yum Brands Inc,YUM,0.095443,123.55,1.57,(1.29%), -222,Dupont De Nemours Inc,DD,0.094185,74.58,1.11,(1.51%), -223,Ameriprise Financial Inc,AMP,0.093691,332.11,5.16,(1.58%), -224,L3harris Technologies Inc,LHX,0.092512,173.16,-2.04,(-1.16%), -225,Fidelity National Info Serv,FIS,0.09207,56.06,0.52,(0.94%), -226,Sysco Corp,SYY,0.091968,65.99,0.78,(1.20%), -227,Moderna Inc,MRNA,0.091789,100.61,1.17,(1.18%), -228,Bank of New York Mellon Corp,BK,0.091699,42.76,0.59,(1.39%), -229,Agilent Technologies Inc,A,0.091382,111.91,1.41,(1.28%), -230,Otis Worldwide Corp,OTIS,0.091228,80.55,1.2,(1.51%), -231,Rockwell Automation Inc,ROK,0.091103,288.26,3.46,(1.21%), -232,Dr Horton Inc,DHI,0.090974,108.96,1.95,(1.82%), -233,Cummins Inc,CMI,0.090916,232.98,3.03,(1.32%), -234,Estee Lauder Companies Cl A,EL,0.090788,139.94,-0.1,(-0.07%), -235,Kinder Morgan Inc,KMI,0.090175,16.71,0.05,(0.27%), -236,Keurig Dr Pepper Inc,KDP,0.088358,31.51,-0.16,(-0.51%), -237,Fastenal Co,FAST,0.087952,55.72,0.66,(1.21%), -238,Xcel Energy Inc,XEL,0.087474,56.5,-0.71,(-1.25%), -239,Devon Energy Corp,DVN,0.087359,48.84,0,(0.01%), -240,Ww Grainger Inc,GWW,0.086956,704.07,3.96,(0.57%), -241,Costar Group Inc,CSGP,0.086756,77.1,0.75,(0.99%), -242,Cencora Inc,COR,0.086188,183.99,-1.17,(-0.63%), -243,United Rentals Inc,URI,0.085093,454.44,8.22,(1.84%), -244,Hershey Co,HSY,0.084755,201.01,-1.55,(-0.76%), -245,Arch Capital Group Ltd,ACGL,0.083799,81.62,0.54,(0.67%), -246,Ppg Industries Inc,PPG,0.083787,130.49,2.46,(1.92%), -247,Global Payments Inc,GPN,0.083671,116.72,1.47,(1.28%), -248,Consolidated Edison Inc,ED,0.083432,85.06,-1.57,(-1.81%), -249,Newmont Corp,NEM,0.082799,36.78,-0.5,(-1.34%), -250,Republic Services Inc,RSG,0.082765,145.01,0.28,(0.19%), -251,Allstate Corp,ALL,0.08254,112.77,-0.25,(-0.22%), -252,Electronic Arts Inc,EA,0.081213,119.76,1.79,(1.51%), -253,Vici Properties Inc,VICI,0.081127,29.28,0.4,(1.37%), -254,Kroger Co,KR,0.080998,44.96,0.48,(1.07%), -255,Public Service Enterprise Gp,PEG,0.080723,56.88,-1.02,(-1.75%), -256,Lennar Corp A,LEN,0.078759,113.41,1.71,(1.53%), -257,Diamondback Energy Inc,FANG,0.078498,158.01,0.78,(0.50%), -258,West Pharmaceutical Services,WST,0.077362,377.15,1.97,(0.52%), -259,Quanta Services Inc,PWR,0.077074,190.82,0.7,(0.37%), -260,Gartner Inc,IT,0.076911,347.78,-1.41,(-0.40%), -261,Aptiv Plc,APTV,0.0757,99.21,3.35,(3.50%), -262,Vulcan Materials Co,VMC,0.075604,207.6,4,(1.97%), -263,Kraft Heinz Co,KHC,0.075468,33.72,-0.31,(-0.90%), -264,Ge Healthcare Technology,GEHC,0.074734,69.81,1.53,(2.24%), -265,Cdw Corp/de,CDW,0.074375,202.53,3.84,(1.93%), -266,Fortive Corp,FTV,0.072323,74.75,1.16,(1.58%), -267,Ingersoll Rand Inc,IR,0.071683,64.52,1.25,(1.97%), -268,Ansys Inc,ANSS,0.071343,299.19,4.85,(1.65%), -269,Extra Space Storage Inc,EXR,0.071269,120.75,0.24,(0.20%), -270,Wec Energy Group Inc,WEC,0.071007,79.67,-0.91,(-1.12%), -271,Martin Marietta Materials,MLM,0.070759,418,8.05,(1.96%), -272,Edison International,EIX,0.068887,63.92,-1.38,(-2.11%), -273,American Water Works Co Inc,AWK,0.068233,123.27,-3.07,(-2.43%), -274,Warner Bros Discovery Inc,WBD,0.068207,10.89,-0.15,(-1.31%), -275,Lyondellbasell Indu Cl A,LYB,0.067294,94.86,-0.11,(-0.11%), -276,Mettler Toledo International,MTD,0.067028,1,112.26,14.48,(1.32%) -277,Avalonbay Communities Inc,AVB,0.066762,171.85,-0.6,(-0.35%), -278,Delta Air Lines Inc,DAL,0.065781,37.32,0.66,(1.79%), -279,T Rowe Price Group Inc,TROW,0.064996,104.73,1.19,(1.15%), -280,Keysight Technologies In,KEYS,0.064934,133.51,3.11,(2.38%), -281,Zimmer Biomet Holdings Inc,ZBH,0.064476,112.14,1.38,(1.24%), -282,Dollar General Corp,DG,0.064042,105.04,0.7,(0.67%), -283,Corning Inc,GLW,0.064037,30.35,0.29,(0.98%), -284,Ebay Inc,EBAY,0.063728,43.45,0.56,(1.31%), -285,Cbre Group Inc A,CBRE,0.063578,73.84,0.35,(0.48%), -286,Weyerhaeuser Co,WY,0.063312,30.4,-0.64,(-2.05%), -287,Church & Dwight Co Inc,CHD,0.062765,91.68,-0.29,(-0.31%), -288,Cardinal Health Inc,CAH,0.062583,88.18,0.14,(0.16%), -289,Hp Inc,HPQ,0.062013,25.73,0.09,(0.36%), -290,Equifax Inc,EFX,0.061821,185.4,4.68,(2.59%), -291,Tractor Supply Company,TSCO,0.061683,205.07,2.06,(1.02%), -292,Willis Towers Watson Plc,WTW,0.06168,211.96,0.35,(0.17%), -293,Hewlett Packard Enterprise,HPE,0.061499,17.7,0.63,(3.66%), -294,Fair Isaac Corp,FICO,0.061481,890.19,4.58,(0.52%), -295,Dollar Tree Inc,DLTR,0.061287,106.46,1.11,(1.05%), -296,Hartford Financial Svcs Grp,HIG,0.061236,72.24,0.53,(0.73%), -297,Resmed Inc,RMD,0.060853,149.81,1.16,(0.78%), -298,Take Two Interactive Softwre,TTWO,0.060753,139.63,1.85,(1.34%), -299,Royal Caribbean Cruises Ltd,RCL,0.060515,94.38,2.42,(2.64%), -300,Xylem Inc,XYL,0.060192,91.4,1.09,(1.20%), -301,Align Technology Inc,ALGN,0.060095,309.06,7.38,(2.45%), -302,Steris Plc,STE,0.060013,221.57,3.67,(1.69%), -303,Broadridge Financial Solutio,BR,0.059572,181.18,-0.04,(-0.02%), -304,Discover Financial Services,DFS,0.059507,86.35,1.09,(1.28%), -305,State Street Corp,STT,0.059411,67.81,1.03,(1.54%), -306,Sba Communications Corp,SBAC,0.059216,198.11,2.05,(1.05%), -307,Monolithic Power Systems Inc,MPWR,0.058699,457.69,16.51,(3.74%), -308,Illumina Inc,ILMN,0.058584,133.02,-0.28,(-0.21%), -309,Dte Energy Company,DTE,0.058057,98.82,-1.72,(-1.71%), -310,M & T Bank Corp,MTB,0.057846,126.63,2.09,(1.68%), -311,Coterra Energy Inc,CTRA,0.057589,27.48,0.34,(1.23%), -312,Eversource Energy,ES,0.057281,57.54,-1.23,(-2.09%), -313,Genuine Parts Co,GPC,0.055796,142.94,0.63,(0.45%), -314,Equity Residential,EQR,0.055712,58.67,0.23,(0.40%), -315,Entergy Corp,ETR,0.055241,92.23,-1.02,(-1.10%), -316,Dover Corp,DOV,0.055103,141.68,1.09,(0.77%), -317,Ameren Corporation,AEE,0.054981,74.6,-1.51,(-1.98%), -318,Ulta Beauty Inc,ULTA,0.054585,398.17,5.73,(1.46%), -319,Teledyne Technologies Inc,TDY,0.054228,414.36,0.92,(0.22%), -320,Nvr Inc,NVR,0.054188,6,27.42,86.42,(1.45%) -321,Targa Resources Corp,TRGP,0.05408,87.52,0.93,(1.08%), -322,Molina Healthcare Inc,MOH,0.053618,333.09,2.03,(0.61%), -323,Wabtec Corp,WAB,0.053425,108.18,1.35,(1.26%), -324,Fleetcor Technologies Inc,FLT,0.053345,260.14,1.28,(0.49%), -325,Albemarle Corp,ALB,0.053229,172.99,10.36,(6.37%), -326,Baxter International Inc,BAX,0.05272,37.54,0.21,(0.57%), -327,Raymond James Financial Inc,RJF,0.052247,101.39,1.84,(1.85%), -328,Mccormick & Co Non Vtg Shrs,MKC,0.051871,74.55,0.46,(0.63%), -329,Invitation Homes Inc,INVH,0.051153,31.73,0.03,(0.11%), -330,Firstenergy Corp,FE,0.050777,34.56,-0.69,(-1.94%), -331,Laboratory Crp of Amer Hldgs,LH,0.05072,204.23,-0.62,(-0.30%), -332,Howmet Aerospace Inc,HWM,0.050386,46.99,0.91,(1.97%), -333,Verisign Inc,VRSN,0.050215,202.93,2.46,(1.23%), -334,Ppl Corp,PPL,0.04902,23.56,-0.39,(-1.61%), -335,Iron Mountain Inc,IRM,0.047985,59.55,0.56,(0.94%), -336,Jacobs Solutions Inc,J,0.047882,136.45,0.27,(0.20%), -337,Intl Flavors & Fragrances,IFF,0.047868,67.84,0.64,(0.95%), -338,Centerpoint Energy Inc,CNP,0.047827,26.68,-0.48,(-1.75%), -339,Darden Restaurants Inc,DRI,0.047736,143.44,2.01,(1.42%), -340,Hologic Inc,HOLX,0.047358,69.99,0.75,(1.08%), -341,First Solar Inc,FSLR,0.047324,161.9,3.29,(2.07%), -342,Expeditors Intl Wash Inc,EXPD,0.046936,114.74,1.08,(0.95%), -343,Brown & Brown Inc,BRO,0.046675,71.15,0.19,(0.26%), -344,Factset Research Systems Inc,FDS,0.046601,443.66,8.47,(1.95%), -345,Fifth Third Bancorp,FITB,0.046598,25.05,0.19,(0.74%), -346,Ventas Inc,VTR,0.046351,42.18,0.77,(1.85%), -347,Marathon Oil Corp,MRO,0.046321,27.51,0.12,(0.45%), -348,Steel Dynamics Inc,STLD,0.046096,106.96,0.52,(0.48%), -349,Bunge Ltd,BG,0.046038,110.67,1.1,(1.00%), -350,Ptc Inc,PTC,0.045951,140.25,1.78,(1.28%), -351,Everest Group Ltd,EG,0.04587,381.3,-0.42,(-0.11%), -352,Cincinnati Financial Corp,CINF,0.045852,104.4,-0.3,(-0.29%), -353,Enphase Energy Inc,ENPH,0.045679,121.39,1.28,(1.07%), -354,Nasdaq Inc,NDAQ,0.04562,49.07,0.74,(1.52%), -355,Akamai Technologies Inc,AKAM,0.045578,107.75,0.79,(0.74%), -356,Cboe Global Markets Inc,CBOE,0.045525,155.28,0.51,(0.33%), -357,Cf Industries Holdings Inc,CF,0.04496,84.93,1.48,(1.78%), -358,Waters Corp,WAT,0.044936,274.46,2.12,(0.78%), -359,Pultegroup Inc,PHM,0.044848,74.85,1.65,(2.25%), -360,Tyler Technologies Inc,TYL,0.044831,387.74,2.43,(0.63%), -361,Principal Financial Group,PFG,0.044705,72.74,0.74,(1.02%), -362,Clorox Company,CLX,0.04465,128.98,-0.17,(-0.13%), -363,Southwest Airlines Co,LUV,0.044478,27.3,0.49,(1.81%), -364,Regions Financial Corp,RF,0.044397,17.16,0.22,(1.27%), -365,Garmin Ltd,GRMN,0.044336,104.65,1.42,(1.38%), -366,Atmos Energy Corp,ATO,0.044128,106.32,-0.14,(-0.13%), -367,Netapp Inc,NTAP,0.044116,76.49,1.54,(2.05%), -368,Textron Inc,TXT,0.043659,79.27,0.33,(0.41%), -369,Cooper Cos Inc,COO,0.04361,318.15,2.23,(0.71%), -370,Kellogg Co,K,0.043517,58.9,-0.22,(-0.38%), -371,Idex Corp,IEX,0.043484,210.72,3.28,(1.58%), -372,Cms Energy Corp,CMS,0.043476,52.78,-0.57,(-1.07%), -373,Skyworks Solutions Inc,SWKS,0.042974,98.55,2.25,(2.33%), -374,Alexandria Real Estate Equit,ARE,0.042466,99.48,0.59,(0.60%), -375,Hunt (Jb) Transprt Svcs Inc,JBHT,0.042319,186.54,0.95,(0.51%), -376,Las Vegas Sands Corp,LVS,0.042222,45.63,-0.53,(-1.15%), -377,Ball Corp,BALL,0.042202,48.27,0.04,(0.08%), -378,Walgreens Boots Alliance Inc,WBA,0.04215,20.97,-0.06,(-0.26%), -379,Teradyne Inc,TER,0.041494,100.04,3.56,(3.68%), -380,Mid America Apartment Comm,MAA,0.041385,128.55,0.48,(0.37%), -381,Epam Systems Inc,EPAM,0.041006,257.76,0.96,(0.37%), -382,Avery Dennison Corp,AVY,0.040961,183.42,1.39,(0.76%), -383,Omnicom Group,OMC,0.040483,74.6,1.21,(1.65%), -384,Huntington Bancshares Inc,HBAN,0.040444,10.25,0.13,(1.24%), -385,Eqt Corp,EQT,0.040251,40,0.39,(0.99%), -386,Tyson Foods Inc Cl A,TSN,0.040042,49.74,-0.37,(-0.74%), -387,Western Digital Corp,WDC,0.039814,45.5,0.94,(2.11%), -388,Northern Trust Corp,NTRS,0.039557,69.29,0.84,(1.23%), -389,Carnival Corp,CCL,0.039206,14.52,0.54,(3.88%), -390,Expedia Group Inc,EXPE,0.038585,102.75,2.5,(2.49%), -391,United Airlines Holdings Inc,UAL,0.038383,42.84,0.81,(1.94%), -392,Quest Diagnostics Inc,DGX,0.038331,123.71,0.31,(0.25%), -393,Axon Enterprise Inc,AXON,0.03828,195.69,1.04,(0.53%), -394,Packaging Corp of America,PKG,0.038236,152.79,0.9,(0.59%), -395,Revvity Inc,RVTY,0.0378,110.55,1.5,(1.38%), -396,Snap on Inc,SNA,0.037774,257.97,4,(1.58%), -397,Pool Corp,POOL,0.037475,353.56,9.86,(2.87%), -398,Essex Property Trust Inc,ESS,0.03733,210.81,0.07,(0.03%), -399,Domino S Pizza Inc,DPZ,0.037258,382.39,2.18,(0.57%), -400,Amcor Plc,AMCR,0.037101,9.09,0.06,(0.61%), -401,Best Buy Co Inc,BBY,0.037071,68.66,0.29,(0.43%), -402,Apa Corp,APA,0.03662,42.49,0.11,(0.27%), -403,Lamb Weston Holdings Inc,LW,0.036553,91.47,0.09,(0.10%), -404,Wr Berkley Corp,WRB,0.036551,65.21,0.86,(1.33%), -405,Conagra Brands Inc,CAG,0.036484,27.44,-0.1,(-0.35%), -406,Lkq Corp,LKQ,0.036449,49.51,0.72,(1.47%), -407,Jm Smucker Co,SJM,0.035767,124.48,-0.96,(-0.77%), -408,Stanley Black & Decker Inc,SWK,0.035567,83.87,0.97,(1.17%), -409,Synchrony Financial,SYF,0.035241,30.73,0.55,(1.84%), -410,Carmax Inc,KMX,0.035202,71.64,-8.05,(-10.10%), -411,Leidos Holdings Inc,LDOS,0.034943,92.2,0.21,(0.23%), -412,Seagate Technology Holdings,STX,0.034918,65.71,1.42,(2.20%), -413,Paycom Software Inc,PAYC,0.034914,259.42,2.34,(0.91%), -414,Celanese Corp,CE,0.034212,127.11,3.81,(3.09%), -415,Trimble Inc,TRMB,0.034136,52.22,3.01,(6.12%), -416,Alliant Energy Corp,LNT,0.03411,48.06,-0.49,(-1.02%), -417,Citizens Financial Group,CFG,0.033972,26.28,0.52,(2.00%), -418,International Paper Co,IP,0.033961,35.1,0.15,(0.41%), -419,Masco Corp,MAS,0.033414,54.58,1.37,(2.58%), -420,Nordson Corp,NDSN,0.033057,223.81,3.73,(1.69%), -421,Loews Corp,L,0.032942,64.16,0.36,(0.56%), -422,Evergy Inc,EVRG,0.032792,50.48,-0.58,(-1.13%), -423,Mosaic Co,MOS,0.03266,35.63,0.43,(1.22%), -424,Molson Coors Beverage Co B,TAP,0.032624,62.29,-0.12,(-0.19%), -425,Zebra Technologies Corp Cl A,ZBRA,0.03257,236.95,11.04,(4.89%), -426,Viatris Inc,VTRS,0.032115,9.8,0.21,(2.14%), -427,Live Nation Entertainment In,LYV,0.032035,83.73,2.71,(3.34%), -428,Host Hotels & Resorts Inc,HST,0.03173,16.38,0.34,(2.11%), -429,Insulet Corp,PODD,0.031493,166.19,4.49,(2.77%), -430,Match Group Inc,MTCH,0.031269,40.07,0.09,(0.23%), -431,Interpublic Group of Cos Inc,IPG,0.031184,29.12,0.39,(1.35%), -432,Hormel Foods Corp,HRL,0.030887,38.15,-0.19,(-0.48%), -433,Incyte Corp,INCY,0.03067,58.93,-0.18,(-0.30%), -434,Udr Inc,UDR,0.030252,35.67,0.28,(0.79%), -435,Jack Henry & Associates Inc,JKHY,0.030211,150.61,2.17,(1.46%), -436,Kimco Realty Corp,KIM,0.029862,17.73,0.24,(1.34%), -437,Aes Corp,AES,0.029775,15.29,-0.65,(-4.05%), -438,Bio Techne Corp,TECH,0.029742,67.67,0.1,(0.15%), -439,Pentair Plc,PNR,0.029592,65.59,0.87,(1.34%), -440,Rollins Inc,ROL,0.029276,37.64,0.2,(0.52%), -441,Mgm Resorts International,MGM,0.028601,36.76,0.27,(0.74%), -442,Ceridian Hcm Holding Inc,CDAY,0.028589,67.38,0.35,(0.52%), -443,Brown Forman Corp Class B,BF.B,0.028542,56.78,0.14,(0.25%), -444,Nisource Inc,NI,0.028365,24.84,-0.35,(-1.37%), -445,Gen Digital Inc,GEN,0.028124,17.83,-0.07,(-0.37%), -446,C.H. Robinson Worldwide Inc,CHRW,0.028048,86.31,0.02,(0.02%), -447,Camden Property Trust,CPT,0.027984,94.56,-0.32,(-0.34%), -448,Charles River Laboratories,CRL,0.027736,195.69,0.75,(0.38%), -449,Healthpeak Properties Inc,PEAK,0.027617,18.15,0.1,(0.58%), -450,Caesars Entertainment Inc,CZR,0.027217,47.52,1.54,(3.36%), -451,Regency Centers Corp,REG,0.027131,59.98,0.85,(1.43%), -452,Keycorp,KEY,0.0269,10.52,0.22,(2.09%), -453,Henry Schein Inc,HSIC,0.026715,73.88,0.62,(0.84%), -454,Globe Life Inc,GL,0.026574,110.04,0.61,(0.56%), -455,Borgwarner Inc,BWA,0.026416,40.72,0.92,(2.31%), -456,F5 Inc,FFIV,0.026087,160.33,2.74,(1.74%), -457,Qorvo Inc,QRVO,0.025849,96.39,1.83,(1.93%), -458,Teleflex Inc,TFX,0.025796,199.42,2.91,(1.48%), -459,Allegion Plc,ALLE,0.025545,104.97,1.68,(1.63%), -460,Westrock Co,WRK,0.025292,35.98,0.23,(0.64%), -461,Eastman Chemical Co,EMN,0.025003,76.99,2.35,(3.15%), -462,Wynn Resorts Ltd,WYNN,0.024938,92.21,0,(-0.00%), -463,Nrg Energy Inc,NRG,0.024681,38.55,-0.03,(-0.08%), -464,Juniper Networks Inc,JNPR,0.024655,27.92,0.42,(1.52%), -465,Pinnacle West Capital,PNW,0.02321,73.45,-0.71,(-0.95%), -466,Hasbro Inc,HAS,0.02308,65.23,0.24,(0.37%), -467,Catalent Inc,CTLT,0.023069,45.85,0.07,(0.15%), -468,American Airlines Group Inc,AAL,0.02296,13,0.39,(3.05%), -469,Fmc Corp,FMC,0.022942,66.03,0.02,(0.03%), -470,Campbell Soup Co,CPB,0.022776,41.15,-0.31,(-0.76%), -471,Smith (a.O.) Corp,AOS,0.022769,66.99,1.54,(2.35%), -472,Boston Properties Inc,BXP,0.02269,59.66,0.79,(1.34%), -473,Huntington Ingalls Industrie,HII,0.022502,204.41,1.22,(0.60%), -474,Fox Corp Class A,FOXA,0.021902,31.47,0.55,(1.76%), -475,Robert Half Inc,RHI,0.021872,73.78,0.64,(0.87%), -476,Assurant Inc,AIZ,0.021618,145.63,-0.13,(-0.09%), -477,Universal Health Services B,UHS,0.021551,127,2.8,(2.25%), -478,Etsy Inc,ETSY,0.021257,63.53,1.64,(2.65%), -479,Marketaxess Holdings Inc,MKTX,0.021132,205.89,4.11,(2.04%), -480,News Corp Class A,NWSA,0.0209,20,0.35,(1.76%), -481,Bio Rad Laboratories A,BIO,0.020548,356.1,3.63,(1.03%), -482,Bath & Body Works Inc,BBWI,0.020412,33.19,1.04,(3.23%), -483,Dentsply Sirona Inc,XRAY,0.020079,33.94,-0.17,(-0.51%), -484,Solaredge Technologies Inc,SEDG,0.020026,132.35,4.34,(3.39%), -485,Whirlpool Corp,WHR,0.019812,131.66,1.03,(0.79%), -486,Franklin Resources Inc,BEN,0.019128,24.55,0.28,(1.14%), -487,Generac Holdings Inc,GNRC,0.018958,110.73,1.84,(1.69%), -488,Norwegian Cruise Line Holdin,NCLH,0.018812,16.96,0.67,(4.08%), -489,Federal Realty Invs Trust,FRT,0.018475,91.45,1.05,(1.16%), -490,Tapestry Inc,TPR,0.01809,28.18,0.23,(0.84%), -491,Invesco Ltd,IVZ,0.017835,14.31,0.22,(1.53%), -492,Paramount Global Class B,PARA,0.017208,12.89,0.11,(0.89%), -493,Vf Corp,VFC,0.015631,16.59,-0.32,(-1.89%), -494,Comerica Inc,CMA,0.014638,41.07,1.12,(2.81%), -495,Davita Inc,DVA,0.014395,95.75,0.01,(0.01%), -496,Zions Bancorp Na,ZION,0.013918,33.96,0.79,(2.39%), -497,Ralph Lauren Corp,RL,0.013127,115.52,0.26,(0.22%), -498,Sealed Air Corp,SEE,0.012794,32.2,0.46,(1.46%), -499,Alaska Air Group Inc,ALK,0.012574,37.04,0.63,(1.73%), -500,Mohawk Industries Inc,MHK,0.011998,85.15,1.23,(1.46%), -501,Organon & Co,OGN,0.011665,16.93,0.34,(2.02%), -502,Dxc Technology Co,DXC,0.011658,20.64,0.29,(1.40%), -503,Fox Corp Class B,FOX,0.010545,29.16,0.53,(1.85%), -504,News Corp Class B,NWS,0.006575,20.75,0.36,(1.74%), diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala index 6de498283..8e8baf046 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala @@ -2,7 +2,7 @@ package org.finos.vuu.core.module.basket object BasketConstants { - object Side{ + object Side { final val Buy = "BUY" final val Sell = "SELL" } diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala index 70a5683f9..8630bcb8e 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala @@ -202,9 +202,4 @@ object BasketModule extends DefaultModule { final val OrderStatus = "orderStatus" final val FilledQty = "filledQty" } - - object Sides{ - final val Buy = "Buy" - final val Sell = "Sell" - } } diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/BasketLoader.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/BasketLoader.scala new file mode 100644 index 000000000..0708e6e09 --- /dev/null +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/BasketLoader.scala @@ -0,0 +1,63 @@ +package org.finos.vuu.core.module.basket.csv + +import com.typesafe.scalalogging.StrictLogging + +import scala.util.control.NonFatal + +class BasketLoader(resourcePath: Option[String] = None) extends StrictLogging { + def loadBasketIds(): Array[String] = { + FileLoader.getFileNames(getPath(resourcePath), ".csv") + .map(fileName => "." + fileName.replace(".csv", "").toUpperCase) + } + + def loadConstituents(basketId: String): Array[Map[String, Any]] = { + try { + val filePath = getPath(resourcePath) + val csvFiles = FileLoader.getFiles(filePath, getBasketFileName(basketId)) + + if (csvFiles.isEmpty) { + logger.error(s"Failed to find constituents file for $basketId in $filePath") + Array.empty + } + else { + val csvFile = csvFiles(0) + logger.info("Loading basket static:" + basketId + "(" + csvFile + ")") + val csvContent = FileLoader.readCsvContent(csvFile) + + logger.info(s"Found ${csvContent.dataRows.length} constituents for basket $basketId") + + csvContent.dataRows.map(row => toConstituentMap(csvContent, row)) + } + } + catch { + case NonFatal(t) => logger.error(s"Failed to get and parse constituents for $basketId", t) + Array.empty + } + } + + private def toConstituentMap(csvContent: CsvContent, row: Array[String]) = { + Map[String, Any]( + "Symbol" -> csvContent.getValue("Symbol", row), + "Last Trade" -> csvContent.getValue("Last Trade", row), + "Name" -> csvContent.getValue("Name", row), + "Weighting" -> csvContent.getValueAsDouble("Weighting", row, 0.0D), + "Volume" -> csvContent.getValue("Volume", row), + "Change" -> csvContent.getValue("Change", row) + ) + } + + private def getBasketFileName(basketId: String) = { + basketId.replace(".", "").toLowerCase + ".csv" + } + + private def getPath(resourcePath: Option[String] = None): String = { + if (resourcePath.isDefined) resourcePath.get + else { + val url = getStaticResourcePath + if (url == null) "" else url.getPath + } + } + + private def getStaticResourcePath = + getClass.getResource("/static") +} diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvContent.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvContent.scala new file mode 100644 index 000000000..f589b7776 --- /dev/null +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvContent.scala @@ -0,0 +1,17 @@ +package org.finos.vuu.core.module.basket.csv + +class CsvContent(data: Array[Array[String]]) { + + private val header = data(0) + val dataRows: Array[Array[String]] = data.tail + + def getValue(headerName: String, row: Array[String]) = { + val index = header.indexOf(headerName) + if (row.length > index && index > -1) row(index) else null + } + + def getValueAsDouble(headerName: String, row: Array[String], defaultValue: Double) = { + val x = getValue(headerName, row) + if (x == null) defaultValue else x.toDouble + } +} diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala deleted file mode 100644 index 13023bffa..000000000 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala +++ /dev/null @@ -1,91 +0,0 @@ -package org.finos.vuu.core.module.basket.csv - -import com.typesafe.scalalogging.StrictLogging - -import scala.io.Source - -object CsvStaticLoader extends StrictLogging { - def loadConstituent(basketId: String): Array[Map[String, Any]] = { - - val staticDirPath = getClass.getResource("/static").getPath - val dir = new java.io.File(staticDirPath) - val csvFiles = dir.listFiles.filter(_.isFile) - .filter(_.getName.endsWith(basketId.replace(".","").toLowerCase + ".csv")) - val csvFile = csvFiles(0) - logger.info("Loading basket static:" + basketId + "(" + csvFile + ")") - val bufferedSource = Source.fromFile(csvFile) - val csv = for (line <- bufferedSource.getLines) yield line.split(",").map(_.trim) - val array = csv.toArray - bufferedSource.close - var data: Map[String, String] = Map() - val header = array(0) - val symbolInd = header.indexOf("Symbol") - val nameInd = header.indexOf("Name") - val lastTradeInd = header.indexOf("Last Trade") - val volumeInd = header.indexOf("Volume") - val weightInd = header.indexOf("Weighting") - val changeInd = header.indexOf("Change") - val list = array.tail.map(e => { - val weighting = if(getValueFromIndex(weightInd, e) == null) 0.0D else getValueFromIndex(weightInd, e).toDouble - Map[String, Any]( - "Symbol" -> getValueFromIndex(symbolInd, e), - "Last Trade" -> getValueFromIndex(lastTradeInd, e), - "Name" -> getValueFromIndex(nameInd, e), - "Weighting" -> weighting, - "Volume" -> getValueFromIndex(volumeInd, e), - "Change" -> getValueFromIndex(changeInd, e) - ) - }) - list - } - - - def load: Array[String] = { - val staticDirPath = getClass.getResource("/static").getPath - val dir = new java.io.File(staticDirPath) - val csvFiles = dir.listFiles.filter(_.isFile) - .filter(_.getName.endsWith(".csv")) - val ids = csvFiles.map(e => "." + e.getName.replace(".csv", "").toUpperCase) - ids - } - - def loadStatic: Map[String, Array[Map[String, String]]] = { - var map: Map[String, Array[Map[String, String]]] = Map() - val staticDirPath = getClass.getResource("/static").getPath - val dir = new java.io.File(staticDirPath) - val csvFiles = dir.listFiles.filter(_.isFile) - .filter(_.getName.endsWith(".csv")) - - csvFiles.foreach(csvFile => { - println(csvFile) - - val bufferedSource = Source.fromFile(csvFile) - val csv = for (line <- bufferedSource.getLines) yield line.split(",").map(_.trim) - val array = csv.toArray - bufferedSource.close - var data: Map[String, String] = Map() - val header = array(0) - val symbolInd = header.indexOf("Symbol") - val nameInd = header.indexOf("Name") - val lastTradeInd = header.indexOf("Last Trade") - val volumeInd = header.indexOf("Volume") - val weightInd = header.indexOf("Weight") - val changeInd = header.indexOf("Change") - val list = array.tail.map(e => Map( - "Symbol" -> getValueFromIndex(symbolInd, e), - "Last Trade" -> getValueFromIndex(lastTradeInd, e), - "Name" -> getValueFromIndex(nameInd, e), - "Weight" -> getValueFromIndex(weightInd, e), - "Volume" -> getValueFromIndex(volumeInd, e), - "Change" -> getValueFromIndex(changeInd, e) - )) - val fileName = csvFile.getName.replace(".csv", "") - map += ("." + fileName.toUpperCase -> list) - }) - map - } - - private def getValueFromIndex(index: Int, e: Array[String]) = { - if (e.length > index && index > -1) e(index) else null - } -} diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/FileLoader.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/FileLoader.scala new file mode 100644 index 000000000..028ccd3f8 --- /dev/null +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/FileLoader.scala @@ -0,0 +1,31 @@ +package org.finos.vuu.core.module.basket.csv + +import java.io.File +import scala.io.Source + +object FileLoader { + def getFileNames(folderPath: String, extensionFilter: String): Array[String] = { + getFiles(folderPath) + .filter(_.getName.endsWith(extensionFilter)) + .map(file => file.getName) + } + + def getFiles(folderPath: String, fileName: String): Array[File] = { + getFiles(folderPath) + .filter(_.getName.equals(fileName)) + } + + def readCsvContent(file: File): CsvContent = { + val bufferedSource = Source.fromFile(file) + val csv = for (line <- bufferedSource.getLines) yield line.split(",").map(_.trim) + val array = csv.toArray + bufferedSource.close + new CsvContent(array) + } + + private def getFiles(folderPath: String): Array[File] = { + val dir = new File(folderPath) + if (dir.listFiles == null) Array.empty + else dir.listFiles.filter(_.isFile) + } +} diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala index 4b1ec3d06..eac0cfbab 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala @@ -4,25 +4,26 @@ import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.thread.RunOnceLifeCycleRunner import org.finos.toolbox.time.Clock import org.finos.vuu.core.module.basket.BasketConstants -import org.finos.vuu.core.module.basket.csv.CsvStaticLoader +import org.finos.vuu.core.module.basket.csv.BasketLoader import org.finos.vuu.core.table.{DataTable, RowWithData} import org.finos.vuu.provider.DefaultProvider class BasketConstituentProvider(val table: DataTable)(implicit lifecycle: LifecycleContainer, clock: Clock) extends DefaultProvider { private val runner = new RunOnceLifeCycleRunner("BasketConstituentProvider", runOnce) + private val basketLoader = new BasketLoader() lifecycle(this).dependsOn(runner) import org.finos.vuu.core.module.basket.BasketModule.BasketConstituentColumnNames._ def runOnce(): Unit = { - val baskets = CsvStaticLoader.load + val baskets = basketLoader.loadBasketIds() baskets.foreach(basketId => updateBasketConstituents(basketId)) } def updateBasketConstituents(basketId: String): Unit = { - val list = CsvStaticLoader.loadConstituent(basketId) + val list = basketLoader.loadConstituents(basketId) list.foreach(row => { if (row.nonEmpty) { @@ -34,7 +35,7 @@ class BasketConstituentProvider(val table: DataTable)(implicit lifecycle: Lifecy val weighting = row("Weighting") val side = BasketConstants.Side.Buy val ricBasketId = symbol + "." + basketId - table.processUpdate(ricBasketId, RowWithData(symbol, Map( + table.processUpdate(ricBasketId, RowWithData(ricBasketId, Map( Ric -> symbol, BasketId -> basketId, RicBasketId -> ricBasketId, diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala index 9f087222d..2708b45ac 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala @@ -4,17 +4,18 @@ import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.thread.RunOnceLifeCycleRunner import org.finos.toolbox.time.Clock import org.finos.vuu.core.module.basket.BasketModule.BasketColumnNames._ -import org.finos.vuu.core.module.basket.csv.CsvStaticLoader +import org.finos.vuu.core.module.basket.csv.BasketLoader import org.finos.vuu.core.table.{DataTable, RowWithData} import org.finos.vuu.provider.DefaultProvider class BasketProvider(val table: DataTable)(implicit lifecycle: LifecycleContainer, clock: Clock) extends DefaultProvider { private val runner = new RunOnceLifeCycleRunner("BasketProvider", runOnce) + private val basketLoader = new BasketLoader() lifecycle(this).dependsOn(runner) def runOnce(): Unit = { - val data = CsvStaticLoader.load + val data = basketLoader.loadBasketIds() data.foreach(id => { table.processUpdate(id, RowWithData(id, Map( @@ -23,7 +24,5 @@ class BasketProvider(val table: DataTable)(implicit lifecycle: LifecycleContaine )), clock.now()) }) } - - override val lifecycleId: String = "org.finos.vuu.core.module.basket.provider.BasketProvider" } diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingConstituentProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingConstituentProvider.scala index 2cc9d691d..74fb2dd71 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingConstituentProvider.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingConstituentProvider.scala @@ -19,14 +19,16 @@ class BasketTradingConstituentProvider(val table: DataTable, val omsApi: OmsApi) table.processUpdate(ack.clientOrderId, RowWithData(ack.clientOrderId, Map[String, Any](BTC.InstanceIdRic -> ack.clientOrderId, BTC.OrderStatus -> OrderStates.ACKED)),clock.now()) } - override def onCancelAck(ack: CancelAck): Unit = ??? + override def onCancelAck(ack: CancelAck): Unit = { + table.processUpdate(ack.clientOrderId, RowWithData(ack.clientOrderId, Map[String, Any](BTC.InstanceIdRic -> ack.clientOrderId, + BTC.OrderStatus -> OrderStates.CANCELLED)), clock.now()) + } override def onReplaceAck(ack: ReplaceAck): Unit = ??? override def onFill(fill: Fill): Unit = { val state = if(fill.orderQty == fill.totalFilledQty) OrderStates.FILLED else OrderStates.ACKED table.processUpdate(fill.clientOrderId, RowWithData(fill.clientOrderId, Map[String, Any](BTC.InstanceIdRic -> fill.clientOrderId, - BTC.FilledQty -> fill.totalFilledQty, BTC.OrderStatus -> state)) - ,clock.now()) + BTC.FilledQty -> fill.totalFilledQty, BTC.OrderStatus -> state)),clock.now()) } }) diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala index b720d80ad..7be804a60 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala @@ -2,11 +2,12 @@ package org.finos.vuu.core.module.basket.service import com.typesafe.scalalogging.StrictLogging import org.finos.toolbox.time.Clock +import org.finos.vuu.core.module.basket.BasketConstants.Side import org.finos.vuu.core.module.basket.BasketModule -import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentTable, Sides} +import org.finos.vuu.core.module.basket.BasketModule.BasketConstituentTable import org.finos.vuu.core.table.{DataTable, RowData, RowWithData, TableContainer} import org.finos.vuu.net.rpc.RpcHandler -import org.finos.vuu.net.{ClientSessionId, RequestContext} +import org.finos.vuu.net.RequestContext import org.finos.vuu.order.oms.OmsApi import org.finos.vuu.viewport._ import java.util.concurrent.atomic.AtomicInteger @@ -14,11 +15,9 @@ import java.util.concurrent.atomic.AtomicInteger object BasketTradeId { private val counter: AtomicInteger = new AtomicInteger(0) - var current:String = "NoneInitalised" //this is for testing but only works if tests that use this doesnt run in parallel def oneNew(user:String): String = { val counterValue = counter.incrementAndGet() - current = user + "-" + "".padTo(5 - counterValue.toString.length, "0").mkString + counterValue - current + user + "-" + "".padTo(5 - counterValue.toString.length, "0").mkString + counterValue } } @@ -57,29 +56,11 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer, va } private def mkTradingBasketRow(sourceBasketId: String, basketTradeName: String, basketTradeInstanceId: String) = { - RowWithData(basketTradeInstanceId, Map(BT.InstanceId -> basketTradeInstanceId, BT.Status -> "OFF-MARKET", BT.BasketId -> sourceBasketId, BT.BasketName -> basketTradeName, BT.Side -> Sides.Buy, BT.Units -> 1)) + RowWithData(basketTradeInstanceId, Map(BT.InstanceId -> basketTradeInstanceId, BT.Status -> "OFF-MARKET", BT.BasketId -> sourceBasketId, BT.BasketName -> basketTradeName, BT.Side -> Side.Buy, BT.Units -> 1)) } - def createBasketFromRpc(basketId: String, name: String)(ctx: RequestContext): ViewPortAction = { - createBasket(basketId, name)(ctx) - } - - def createBasket(selection: ViewPortSelection, session: ClientSessionId): ViewPortAction = { - - val basketId = selection.rowKeyIndex.map({ case (key, _) => key }).toList.head - - val instanceKey = BasketTradeId.oneNew(session.user) - - createBasketInternal(basketId, instanceKey, instanceKey, session) - } - - def createBasket(basketId: String, name: String)(ctx: RequestContext): ViewPortAction = { + def createBasket(sourceBasketId: String, basketTradeName: String)(ctx: RequestContext): ViewPortAction = { val basketTradeId = BasketTradeId.oneNew(ctx.session.user) - createBasketInternal(basketId, name, basketTradeId, ctx.session) - } - - private def createBasketInternal(sourceBasketId: String, basketTradeName: String, basketTradeId: String, sessionId: ClientSessionId) = { - val constituents = getConstituentsForSourceBasket(sourceBasketId) tableContainer.getTable(BasketModule.BasketTradingTable) match { @@ -102,11 +83,6 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer, va logger.error("Cannot find the Basket Trading Constituent.") } - NoAction() + ViewPortCreateSuccess(basketTradeId) } - - override def menuItems(): ViewPortMenu = ViewPortMenu( - new SelectionViewPortMenuItem("Create New", "", (sel, sess) => this.createBasket(sel, sess), "CREATE_NEW_BASKET"), - ) - } diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala index 66a33d5b3..ca3f5d02f 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala @@ -5,9 +5,9 @@ import org.finos.toolbox.time.Clock import org.finos.vuu.api.JoinTableDef import org.finos.vuu.core.module.basket.BasketConstants.Side import org.finos.vuu.core.module.basket.BasketModule -import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingColumnNames => BTColumnName, BasketTradingConstituentColumnNames => ColumnName} +import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentColumnNames => BCColumnName, BasketTradingColumnNames => BTColumnName, BasketTradingConstituentColumnNames => ColumnName} import org.finos.vuu.core.module.basket.result.ErrorReason -import org.finos.vuu.core.table.{DataTable, JoinTable, RowWithData, TableContainer} +import org.finos.vuu.core.table.{DataTable, JoinTable, RowData, RowWithData, TableContainer} import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} import org.finos.vuu.net.{ClientSessionId, RequestContext} import org.finos.vuu.viewport._ @@ -64,21 +64,34 @@ class BasketTradingConstituentJoinService(val table: DataTable, val tableContain val basketId = tradeRow.get(BTColumnName.BasketId).asInstanceOf[String] val tradeUnit = tradeRow.get(BTColumnName.Units).asInstanceOf[Int] + val basketConstituentRows = getConstituentsWith(ric) //todo what to do when multiple result? + val description = + if(basketConstituentRows.nonEmpty) + basketConstituentRows.head.get(BCColumnName.Description).asInstanceOf[String] + else "" + val newRow = mkTradingConstituentRow( basketTradeInstanceId = tradeId, sourceBasketId = basketId, tradeUnit = tradeUnit, - ric = ric) + ric = ric, + description = description) //todo should we guard against adding row for ric that already exist? updateJoinTable(Array(newRow)) match { - case Right(_) => ViewPortRpcSuccess() + case Right(_) => ViewPortCreateSuccess(newRow.key) case Left(errorReason) => ViewPortRpcFailure(errorReason.reason) } } } + private def getConstituentsWith(ric: String): List[RowData] = { + val table = tableContainer.getTable(BasketModule.BasketConstituentTable) + val keys = table.primaryKeys.toList + keys.map(key => table.pullRow(key)).filter(_.get(BCColumnName.Ric).toString == ric) + } + private def onEditCell(key: String, columnName: String, data: Any, vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { try { getBaseTable() match { @@ -180,7 +193,7 @@ class BasketTradingConstituentJoinService(val table: DataTable, val tableContain } } - private def mkTradingConstituentRow(basketTradeInstanceId: String, sourceBasketId: String, tradeUnit: Int, ric: String): RowWithData = { + private def mkTradingConstituentRow(basketTradeInstanceId: String, sourceBasketId: String, tradeUnit: Int, ric: String, description: String): RowWithData = { val constituentKey = s"$basketTradeInstanceId.$ric" val weighting: Double = 0.1 RowWithData( @@ -191,7 +204,7 @@ class BasketTradingConstituentJoinService(val table: DataTable, val tableContain ColumnName.InstanceId -> basketTradeInstanceId, ColumnName.InstanceIdRic -> constituentKey, ColumnName.Quantity -> (weighting * 100).asInstanceOf[Long], - ColumnName.Description -> "", //todo look up description from instrument table + ColumnName.Description -> description, ColumnName.Side -> Side.Buy, ColumnName.Weighting -> weighting, ColumnName.PriceStrategyId -> 2, diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala index a738b2887..8a805e9bc 100644 --- a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala @@ -3,14 +3,18 @@ package org.finos.vuu.core.module.basket.service import com.typesafe.scalalogging.StrictLogging import org.finos.toolbox.time.Clock import org.finos.vuu.core.module.basket.BasketModule -import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingConstituentTable, Sides} -import org.finos.vuu.core.table.{DataTable, RowWithData, TableContainer, ViewPortColumnCreator} +import org.finos.vuu.core.module.basket.BasketConstants.Side +import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingConstituentTable} +import org.finos.vuu.core.table.{DataTable, RowData, RowWithData, TableContainer, ViewPortColumnCreator} import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} import org.finos.vuu.net.{ClientSessionId, RequestContext} -import org.finos.vuu.order.oms.{NewOrder, OmsApi} +import org.finos.vuu.order.oms.{CancelOrder, NewOrder, OmsApi} import org.finos.vuu.viewport._ -trait BasketTradingServiceIF extends EditRpcHandler{ + +trait BasketTradingServiceIF extends EditRpcHandler { def sendToMarket(basketInstanceId: String)(ctx: RequestContext): ViewPortAction + + def takeOffMarket(basketInstanceId: String)(ctx: RequestContext): ViewPortAction } @@ -20,18 +24,14 @@ class BasketTradingService(val table: DataTable, val tableContainer: TableContai /** - * Send basket to market + * Send basket to market rpc call */ - override def sendToMarket(name: String)(ctx: RequestContext): ViewPortAction = { - val tableRow = table.asTable.pullRow(name) - - logger.info("Sending basket to market:" + name + " (row:" + tableRow + ")") + override def sendToMarket(basketInstanceId: String)(ctx: RequestContext): ViewPortAction = { + val tableRow = table.asTable.pullRow(basketInstanceId) - val tradingConsTable = tableContainer.getTable(BasketModule.BasketTradingConstituentTable) + logger.info("Sending basket to market:" + basketInstanceId + " (row:" + tableRow + ")") - val constituents = tradingConsTable.primaryKeys.toList - .map(tradingConsTable.pullRow) - .filter(_.get(BTC.InstanceId) == name) + val constituents = getConstituents(basketInstanceId) constituents.foreach(constituentRow => { @@ -48,12 +48,43 @@ class BasketTradingService(val table: DataTable, val tableContainer: TableContai omsApi.createOrder(nos) }) - table.processUpdate(name, RowWithData(name, - Map(BT.InstanceId -> name, BT.Status -> BasketStates.ON_MARKET)), clock.now()) + updateBasketTradeStatus(basketInstanceId, state = BasketStates.ON_MARKET) ViewPortEditSuccess() } + /** + * Take basket off market rpc call + */ + override def takeOffMarket(basketInstanceId: String)(ctx: RequestContext): ViewPortAction = { + val tableRow = table.asTable.pullRow(basketInstanceId) + + logger.info("Tasking basket off market:" + basketInstanceId + " (row:" + tableRow + ")") + + updateBasketTradeStatus(basketInstanceId, BasketStates.OFF_MARKET) + + getConstituents(basketInstanceId) + .flatMap(c => omsApi.getOrderId(clientOrderId = c.get(BTC.InstanceIdRic).toString)) + .foreach(orderId => omsApi.cancelOrder(CancelOrder(orderId))) + + ViewPortEditSuccess() + } + + private def getConstituents(basketInstanceId: String): List[RowData] = { + val tradingConsTable = tableContainer.getTable(BasketModule.BasketTradingConstituentTable) + + tradingConsTable.primaryKeys.toList + .map(tradingConsTable.pullRow) + .filter(_.get(BTC.InstanceId) == basketInstanceId) + } + + private def updateBasketTradeStatus(basketInstanceId: String, state: String): Unit = { + table.processUpdate( + basketInstanceId, + RowWithData(basketInstanceId, Map(BT.InstanceId -> basketInstanceId, BT.Status -> state)), + clock.now()) + } + private def onEditCell(key: String, columnName: String, data: Any, vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { logger.info("Change requested for cell value for key:" + key + "(" + columnName + ":" + data + ")") @@ -80,8 +111,8 @@ class BasketTradingService(val table: DataTable, val tableContainer: TableContai val constituents = constituentTable.primaryKeys.map(key => constituentTable.pullRow(key)).filter(_.get(BTC.InstanceId) == key) constituents.foreach(row => { val newSide = row.get(BTC.Side) match { - case Sides.Buy => Sides.Sell - case _ => Sides.Buy + case Side.Buy => Side.Sell + case _ => Side.Buy } constituentTable.processUpdate(row.key(), RowWithData(row.key(), Map(BTC.InstanceIdRic -> row.key(), BTC.Side -> newSide)), clock.now()) }) diff --git a/example/basket/src/test/resources/constituents/ftse100.csv b/example/basket/src/test/resources/constituents/ftse100.csv new file mode 100644 index 000000000..57cee0058 --- /dev/null +++ b/example/basket/src/test/resources/constituents/ftse100.csv @@ -0,0 +1,4 @@ +Symbol,Name,Last Trade,Change,Volume, Weighting +AAL.L,Anglo American PLC,436.35,5.35,5799089,0.0278736825813547 +ABF.L,Associated British Foods PLC,435.60,7.40,86808,0.000417248060431947 +ADM.L,Admiral Group PLC,1,627.00,,86808,0.000417248060431947 \ No newline at end of file diff --git a/example/basket/src/test/resources/constituents/ftsewitherror.csv b/example/basket/src/test/resources/constituents/ftsewitherror.csv new file mode 100644 index 000000000..b11163374 --- /dev/null +++ b/example/basket/src/test/resources/constituents/ftsewitherror.csv @@ -0,0 +1,4 @@ +Symbol,Name,Last Trade,Change,Volume, Weighting +AAL.L,Anglo American PLC,436.35,5.35,5799089,0.0278736825813547 +ABF.L,Associated British Foods PLC,435.60,7.40,86808,NotANumber +ADM.L,Admiral Group PLC,1,627.00,,86808,0.000417248060431947 \ No newline at end of file diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketConstituentMutateTest.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketConstituentMutateTest.scala index 6fe045421..e3493813b 100644 --- a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketConstituentMutateTest.scala +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketConstituentMutateTest.scala @@ -33,9 +33,9 @@ class BasketConstituentMutateTest extends VuuServerTestCase { vuuServer.login("testUser", "testToken") val basketName = "test_basket1" - val tradeId = GivenBasketTrade(vuuServer.tableContainer, basketName, "Buy") + val tradeId = GivenBasketTrade(vuuServer.tableContainer, basketName, "BUY") GivenPrices(vuuServer.tableContainer, List(("VOD.L", 1.1, 1.4), ("BP.L", 2.1, 2.4))) - GivenBasketTradeConstituentsJoin(vuuServer.tableContainer, tradeId, Map(("VOD.L" -> "Buy"), ("BP.L" -> "Sell"))) + GivenBasketTradeConstituentsJoin(vuuServer.tableContainer, tradeId, Map(("VOD.L" -> "BUY"), ("BP.L" -> "SELL"))) val vpBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) val vpBasketTradingConsJoin = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentJoin) @@ -60,9 +60,9 @@ class BasketConstituentMutateTest extends VuuServerTestCase { assertVpEq(filterByVp(vpBasketTradingConsJoin, updates)) { Table( ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "bid", "ask", "filledQty", "orderStatus"), - (10L, "Buy", "testUser-00001", "testUser-00001.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 2.1, 2.4, 0, "PENDING"), - (10L, "Sell", "testUser-00001", "testUser-00001.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, null, null, 0, "PENDING"), - (10L, "Sell", "testUser-00001", "testUser-00001.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 1.1, 1.4, 0, "PENDING") + (10L, "BUY", "testUser-00001", "testUser-00001.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 2.1, 2.4, 0, "PENDING"), + (10L, "SELL", "testUser-00001", "testUser-00001.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, null, null, 0, "PENDING"), + (10L, "SELL", "testUser-00001", "testUser-00001.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 1.1, 1.4, 0, "PENDING") ) } } diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala index f847d55e6..635db6e65 100644 --- a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala @@ -7,10 +7,10 @@ import org.finos.vuu.api.ViewPortDef import org.finos.vuu.core.module.TableDefContainer import org.finos.vuu.core.module.basket.service.{BasketServiceIF, BasketTradeId, BasketTradingServiceIF} import org.finos.vuu.core.module.price.PriceModule -import org.finos.vuu.core.table.TableTestHelper.combineQs import org.finos.vuu.order.oms.OmsApi import org.finos.vuu.test.VuuServerTestCase import org.finos.vuu.util.table.TableAsserts.assertVpEq +import org.finos.vuu.viewport.ViewPortCreateSuccess import org.scalatest.prop.Tables.Table class BasketCreateTest extends VuuServerTestCase { @@ -54,21 +54,24 @@ class BasketCreateTest extends VuuServerTestCase { val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](viewportBasket) - val action = basketService.createBasket(".FTSE", "TestBasket")(vuuServer.requestContext) + val vpAction = basketService.createBasket(".FTSE", "TestBasket")(vuuServer.requestContext) + + assert(vpAction.isInstanceOf[ViewPortCreateSuccess]) + val basketTradeInstanceId = vpAction.asInstanceOf[ViewPortCreateSuccess].key val viewportBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) val basketTradingService = vuuServer.getViewPortRpcServiceProxy[BasketTradingServiceIF](viewportBasketTrading) //CJS: I don't like this forced cast, need to look at that a bit - basketTradingService.editCellAction().func(BasketTradeId.current, BT.Units, 100.asInstanceOf[Object], viewportBasketTrading, vuuServer.session) + basketTradingService.editCellAction().func(basketTradeInstanceId, BT.Units, 100.asInstanceOf[Object], viewportBasketTrading, vuuServer.session) vuuServer.runOnce() assertVpEq(combineQsForVp(viewportBasketTrading)) { Table( ("basketId", "instanceId", "basketName", "units", "status", "filledPct", "totalNotionalUsd", "totalNotional", "fxRateToUsd", "side"), - (".FTSE", BasketTradeId.current, "TestBasket", 100, "OFF-MARKET", null, null, null, null, "Buy") + (".FTSE", basketTradeInstanceId, "TestBasket", 100, "OFF-MARKET", null, null, null, null, "BUY") ) } } diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala index 6ede3b3ef..c54e31162 100644 --- a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala @@ -11,6 +11,7 @@ import org.finos.vuu.core.module.price.PriceModule import org.finos.vuu.order.oms.OmsApi import org.finos.vuu.test.{TestVuuServer, VuuServerTestCase} import org.finos.vuu.util.table.TableAsserts.assertVpEq +import org.finos.vuu.viewport.ViewPortCreateSuccess import org.scalatest.prop.Tables.Table class BasketMutateOffMarketTest extends VuuServerTestCase { @@ -60,16 +61,17 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(combineQsForVp(vpConstituent)) { Table( ("ricBasketId", "ric", "basketId", "weighting", "lastTrade", "change", "volume", "description", "side"), - ("BP.L.FTSE", "BP.L", ".FTSE", 0.1, null, null, null, "Beyond Petroleum", "Buy"), - ("BT.L.FTSE", "BT.L", ".FTSE", 0.1, null, null, null, "British Telecom", "Sell"), - ("VOD.L.FTSE", "VOD.L", ".FTSE", 0.1, null, null, null, "Vodafone", "Buy") + ("BP.L.FTSE", "BP.L", ".FTSE", 0.1, null, null, null, "Beyond Petroleum", "BUY"), + ("BT.L.FTSE", "BT.L", ".FTSE", 0.1, null, null, null, "British Telecom", "SELL"), + ("VOD.L.FTSE", "VOD.L", ".FTSE", 0.1, null, null, null, "Vodafone", "BUY") ) } Then("Get the Basket RPC Service and call create basket") val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](vpBasket) - basketService.createBasket(".FTSE", "MyCustomBasket")(vuuServer.requestContext) - val basketTradeInstanceId = BasketTradeId.current + val vpAction = basketService.createBasket(".FTSE", "MyCustomBasket")(vuuServer.requestContext) + assert(vpAction.isInstanceOf[ViewPortCreateSuccess]) + val basketTradeInstanceId = vpAction.asInstanceOf[ViewPortCreateSuccess].key val vpBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) @@ -80,7 +82,7 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(combineQsForVp(vpBasketTrading)) { Table( ("instanceId", "basketId", "basketName", "status", "units", "filledPct", "fxRateToUsd", "totalNotional", "totalNotionalUsd", "side"), - (basketTradeInstanceId, ".FTSE", "MyCustomBasket", "OFF-MARKET", 1, null, null, null, null, "Buy") + (basketTradeInstanceId, ".FTSE", "MyCustomBasket", "OFF-MARKET", 1, null, null, null, null, "BUY") ) } @@ -91,16 +93,16 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(combineQsForVp(vpBasketTradingCons)) { Table( ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"), - (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (10L, "Sell", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") ) } val basketTradingService = vuuServer.getViewPortRpcServiceProxy[BasketTradingServiceIF](vpBasketTrading) When("we edit the side of the parent basket") - basketTradingService.editCellAction().func(basketTradeInstanceId, "side", "Sell", vpBasketTrading, vuuServer.session) + basketTradingService.editCellAction().func(basketTradeInstanceId, "side", "SELL", vpBasketTrading, vuuServer.session) Then("get all the updates that have occurred for all view ports from the outbound queue") val updates = combineQs(vpBasketTrading) @@ -109,7 +111,7 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(filterByVp(vpBasketTrading, updates)) { Table( ("instanceId", "basketId", "basketName", "status", "units", "filledPct", "fxRateToUsd", "totalNotional", "totalNotionalUsd", "side"), - (basketTradeInstanceId, ".FTSE", "MyCustomBasket", "OFF-MARKET", 1, null, null, null, null, "Sell") + (basketTradeInstanceId, ".FTSE", "MyCustomBasket", "OFF-MARKET", 1, null, null, null, null, "SELL") ) } @@ -118,9 +120,9 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(filterByVp(vpBasketTradingCons, updates)) { Table( ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"), - (10L, "Sell", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (10L, "Sell", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") + (10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") ) } @@ -131,9 +133,9 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(filterByVp(vpBasketTradingCons, combineQs(vpBasketTrading))) { Table( ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"), - (100L, "Sell", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (100L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (100L, "Sell", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") + (100L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (100L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (100L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") ) } } @@ -152,15 +154,14 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { vuuServer.login("testUser", "testToken2") - GivenBasketTradeExist(vuuServer, ".FTSE", "MyCustomBasket") - val basketTradeInstanceId = BasketTradeId.current + val basketTradeInstanceId = GivenBasketTradeExist(vuuServer, ".FTSE", "MyCustomBasket") val vpBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) val vpBasketTradingCons = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentTable) val basketTradingService = vuuServer.getViewPortRpcServiceProxy[BasketTradingServiceIF](vpBasketTrading) When("we edit the side of the parent basket to same side as current value") - basketTradingService.editCellAction().func(basketTradeInstanceId, "side", "Buy", vpBasketTrading, vuuServer.session) + basketTradingService.editCellAction().func(basketTradeInstanceId, "side", "BUY", vpBasketTrading, vuuServer.session) vuuServer.runOnce() Then("get all the updates that have occurred for all view ports from the outbound queue") @@ -170,7 +171,7 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(filterByVp(vpBasketTrading, updates2)) { Table( ("instanceId", "basketId", "basketName", "status", "units", "filledPct", "fxRateToUsd", "totalNotional", "totalNotionalUsd", "side"), - (basketTradeInstanceId, ".FTSE", "MyCustomBasket", "OFF-MARKET", 1, null, null, null, null, "Buy") + (basketTradeInstanceId, ".FTSE", "MyCustomBasket", "OFF-MARKET", 1, null, null, null, null, "BUY") ) } @@ -178,74 +179,73 @@ class BasketMutateOffMarketTest extends VuuServerTestCase { assertVpEq(filterByVp(vpBasketTradingCons, updates2)) { Table( ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"), - (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (10L, "Sell", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), - (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") ) } } } - //TODO oin table cannot be tested currently as it doesnt get updated when underlying table gets updated -// Scenario("Adding new constituents by ric should add it to basket trading") { -// import BasketModule._ -// implicit val clock: Clock = new TestFriendlyClock(10001L) -// implicit val lifecycle: LifecycleContainer = new LifecycleContainer() -// implicit val tableDefContainer: TableDefContainer = new TableDefContainer(Map()) -// implicit val metricsProvider: MetricsProvider = new MetricsProviderImpl -// -// val omsApi = OmsApi() -// withVuuServer(PriceModule(), BasketModule(omsApi)) { -// vuuServer => -// -// vuuServer.login("testUser", "testToken2") -// -// GivenBasketTradeExist(vuuServer, ".FTSE", "MyCustomBasket") -// val basketTradeInstanceId = BasketTradeId.current -// -// val vpBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) -// val vpBasketTradingCons = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentTable) -// val vpBasketTradingConsJoin = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentJoin) -// val basketTradingConstituentJoinService = vuuServer.getViewPortRpcServiceProxy[BasketTradingConstituentJoinServiceIF](vpBasketTradingConsJoin) -// -// vuuServer.runOnce() -// -// When("we edit the side of the parent basket to same side as current value") -// basketTradingConstituentJoinService.addConstituent("0001.HK")(vuuServer.requestContext) -// vuuServer.runOnce() -// -// Then("get all the updates that have occurred for all view ports from the outbound queue") -// val updates = combineQs(vpBasketTradingConsJoin) -// -// -// //todo map description -// //todo should basketid be where the stock was sourced from? in this case .HSI? -// -// And("assert the basket trading constituent table has not changed sides") -// assertVpEq(filterByVp(vpBasketTradingCons, updates)) { -// Table( -// ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"), -// (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), -// (10L, "Sell", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), -// (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), -// (10L, "Buy", basketTradeInstanceId, s"$basketTradeInstanceId.0001.HK", ".FTSE", "0001.HK", "", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") -// ) -// } -// } -// } + //TODO join table cannot be tested currently as it doesnt get updated when underlying table gets updated + ignore("Adding new constituents by ric should add it to basket trading") { + import BasketModule._ + implicit val clock: Clock = new TestFriendlyClock(10001L) + implicit val lifecycle: LifecycleContainer = new LifecycleContainer() + implicit val tableDefContainer: TableDefContainer = new TableDefContainer(Map()) + implicit val metricsProvider: MetricsProvider = new MetricsProviderImpl + + val omsApi = OmsApi() + withVuuServer(PriceModule(), BasketModule(omsApi)) { + vuuServer => + + vuuServer.login("testUser", "testToken2") + + val basketTradeInstanceId = GivenBasketTradeExist(vuuServer, ".FTSE", "MyCustomBasket") + + val vpBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) + val vpBasketTradingCons = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentTable) + val vpBasketTradingConsJoin = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentJoin) + val basketTradingConstituentJoinService = vuuServer.getViewPortRpcServiceProxy[BasketTradingConstituentJoinServiceIF](vpBasketTradingConsJoin) + + vuuServer.runOnce() + + When("we edit the side of the parent basket to same side as current value") + basketTradingConstituentJoinService.addConstituent("0001.HK")(vuuServer.requestContext) + vuuServer.runOnce() + + Then("get all the updates that have occurred for all view ports from the outbound queue") + val updates = combineQs(vpBasketTradingConsJoin) + + //todo should basketid be where the stock was sourced from? in this case .HSI? + + And("assert the basket trading constituent table has added row") + assertVpEq(filterByVp(vpBasketTradingCons, updates)) { + Table( + ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.0001.HK", ".FTSE", "0001.HK", "", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") + ) + } + } + } } - def GivenBasketTradeExist(vuuServer: TestVuuServer, basketId: String, basketTradeName: String): Unit = { + def GivenBasketTradeExist(vuuServer: TestVuuServer, basketId: String, basketTradeName: String): String = { val basketProvider = vuuServer.getProvider(BasketModule.NAME, BasketModule.BasketTable) basketProvider.tick(".FTSE", Map(B.Id -> ".FTSE", B.Name -> ".FTSE 100", B.NotionalValue -> 1000001, B.NotionalValueUsd -> 1500001)) val constituentProvider = vuuServer.getProvider(BasketModule.NAME, BasketModule.BasketConstituentTable) - constituentProvider.tick("VOD.L.FTSE", Map(BC.RicBasketId -> "VOD.L.FTSE", BC.Ric -> "VOD.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "Buy", BC.Description -> "Vodafone")) - constituentProvider.tick("BT.L.FTSE", Map(BC.RicBasketId -> "BT.L.FTSE", BC.Ric -> "BT.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "Sell", BC.Description -> "British Telecom")) - constituentProvider.tick("BP.L.FTSE", Map(BC.RicBasketId -> "BP.L.FTSE", BC.Ric -> "BP.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "Buy", BC.Description -> "Beyond Petroleum")) + constituentProvider.tick("VOD.L.FTSE", Map(BC.RicBasketId -> "VOD.L.FTSE", BC.Ric -> "VOD.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Vodafone")) + constituentProvider.tick("BT.L.FTSE", Map(BC.RicBasketId -> "BT.L.FTSE", BC.Ric -> "BT.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "SELL", BC.Description -> "British Telecom")) + constituentProvider.tick("BP.L.FTSE", Map(BC.RicBasketId -> "BP.L.FTSE", BC.Ric -> "BP.L", BC.BasketId -> basketId, BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Beyond Petroleum")) val vpBasket = vuuServer.createViewPort(BasketModule.NAME, BasketModule.BasketTable) val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](vpBasket) - basketService.createBasket(basketId, basketTradeName)(vuuServer.requestContext) + val vpAction = basketService.createBasket(basketId, basketTradeName)(vuuServer.requestContext) + assert(vpAction.isInstanceOf[ViewPortCreateSuccess]) + vpAction.asInstanceOf[ViewPortCreateSuccess].key } } \ No newline at end of file diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketSendToMarketTest.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketSendToMarketTest.scala index 36fc23848..15b40173c 100644 --- a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketSendToMarketTest.scala +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketSendToMarketTest.scala @@ -11,6 +11,7 @@ import org.finos.vuu.core.module.price.PriceModule import org.finos.vuu.order.oms.OmsApi import org.finos.vuu.test.VuuServerTestCase import org.finos.vuu.util.table.TableAsserts.assertVpEq +import org.finos.vuu.viewport.ViewPortCreateSuccess import org.scalatest.prop.Tables.Table class BasketSendToMarketTest extends VuuServerTestCase { @@ -50,13 +51,25 @@ class BasketSendToMarketTest extends VuuServerTestCase { Then("Get the Basket RPC Service and call create basket") val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](vpBasket) - basketService.createBasket(".FTSE", "TestBasket")(vuuServer.requestContext) - val basketTradeInstanceId = BasketTradeId.current + val vpAction = basketService.createBasket(".FTSE", "TestBasket")(vuuServer.requestContext) + assert(vpAction.isInstanceOf[ViewPortCreateSuccess]) + val basketTradeInstanceId = vpAction.asInstanceOf[ViewPortCreateSuccess].key val vpBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) + val vpBasketTradingCons = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentTable) vuuServer.runOnce() + And("Check the trading constituents are created") + assertVpEq(combineQsForVp(vpBasketTradingCons)) { + Table( + ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId", "filledQty", "orderStatus"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "SELL", basketTradeInstanceId, s"$basketTradeInstanceId.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING"), + (10L, "BUY", basketTradeInstanceId, s"$basketTradeInstanceId.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2, 0, "PENDING") + ) + } + val tradingService = vuuServer.getViewPortRpcServiceProxy[BasketTradingServiceIF](vpBasketTrading) And("send the basket to market") @@ -68,7 +81,20 @@ class BasketSendToMarketTest extends VuuServerTestCase { assertVpEq(combineQsForVp(vpBasketTrading)) { Table( ("instanceId", "basketId", "basketName", "status", "units", "filledPct", "fxRateToUsd", "totalNotional", "totalNotionalUsd", "side"), - (basketTradeInstanceId, ".FTSE", "TestBasket", "ON_MARKET", 1, null, null, null, null, "Buy") + (basketTradeInstanceId, ".FTSE", "TestBasket", "ON_MARKET", 1, null, null, null, null, "BUY") + ) + } + + Then("Take the basket off the market") + tradingService.takeOffMarket(basketTradeInstanceId)(vuuServer.requestContext) + + vuuServer.runOnce() + + And("verify basket is on market") + assertVpEq(combineQsForVp(vpBasketTrading)) { + Table( + ("instanceId", "basketId", "basketName", "status", "units", "filledPct", "fxRateToUsd", "totalNotional", "totalNotionalUsd", "side"), + (basketTradeInstanceId, ".FTSE", "TestBasket", "OFF_MARKET", 1, null, null, null, null, "BUY") ) } } diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala index 540cb1d2d..657af5767 100644 --- a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala @@ -20,8 +20,8 @@ object BasketTestCaseHelper { //symbol + "." + basketId //Columns.fromNames(BC.RicBasketId.string(), BC.Ric.string(), BC.BasketId.string(), BC.Weighting.double(), BC.LastTrade.string(), BC.Change.string(), // BC.Volume.string(), BC.Side.string()) - provider.tick("VOD.L.FTSE", Map(BC.RicBasketId -> "VOD.L.FTSE", BC.Ric -> "VOD.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "Buy", BC.Description -> "Vodafone")) - provider.tick("BT.L.FTSE", Map(BC.RicBasketId -> "BT.L.FTSE", BC.Ric -> "BT.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "Sell", BC.Description -> "British Telecom")) - provider.tick("BP.L.FTSE", Map(BC.RicBasketId -> "BP.L.FTSE", BC.Ric -> "BP.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "Buy", BC.Description -> "Beyond Petroleum")) + provider.tick("VOD.L.FTSE", Map(BC.RicBasketId -> "VOD.L.FTSE", BC.Ric -> "VOD.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Vodafone")) + provider.tick("BT.L.FTSE", Map(BC.RicBasketId -> "BT.L.FTSE", BC.Ric -> "BT.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "SELL", BC.Description -> "British Telecom")) + provider.tick("BP.L.FTSE", Map(BC.RicBasketId -> "BP.L.FTSE", BC.Ric -> "BP.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "BUY", BC.Description -> "Beyond Petroleum")) } } diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestHelper/TestDataFactory.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestHelper/TestDataFactory.scala index a7ce889b1..526a13f93 100644 --- a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestHelper/TestDataFactory.scala +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestHelper/TestDataFactory.scala @@ -1,7 +1,7 @@ package org.finos.vuu.core.module.basket.TestHelper +import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingColumnNames => BT, BasketTradingConstituentColumnNames => BTC} import org.finos.vuu.core.table.RowWithData -import org.finos.vuu.core.module.basket.BasketModule.{Sides, BasketColumnNames => B, BasketConstituentColumnNames => BC, BasketTradingColumnNames => BT, BasketTradingConstituentColumnNames => BTC} object TestDataFactory { def uuid = java.util.UUID.randomUUID.toString diff --git a/example/basket/src/test/scala/org/finos/vuu/csv/BasketLoaderTests.scala b/example/basket/src/test/scala/org/finos/vuu/csv/BasketLoaderTests.scala new file mode 100644 index 000000000..2832e7c7b --- /dev/null +++ b/example/basket/src/test/scala/org/finos/vuu/csv/BasketLoaderTests.scala @@ -0,0 +1,63 @@ +package org.finos.vuu.csv + +import org.finos.vuu.core.module.basket.csv.BasketLoader +import org.scalatest.featurespec.AnyFeatureSpec +class BasketLoaderTests extends AnyFeatureSpec { + + Feature("Basket ids loading Test Case") { + + Scenario("Can successfully get basket ids from files") { + val testResourcePath = this.getClass.getResource("/constituents").getPath + val basketLoader = new BasketLoader(Some(testResourcePath)) + val basketIds = basketLoader.loadBasketIds() + + assert(basketIds.length == 2) + assert(basketIds.contains(".FTSE100")) + assert(basketIds.contains(".FTSEWITHERROR")) + } + + Scenario("When no file found return empty") { + val testResourcePath = this.getClass.getResource("/constituents").getPath + "/doesNotExist" + val basketLoader = new BasketLoader(Some(testResourcePath)) + val basketIds = basketLoader.loadBasketIds() + + assert(basketIds.length == 0) + } + } + + Feature("Basket constituent loading Test Case") { + + val testResourcePath = this.getClass.getResource("/constituents").getPath + val basketLoader = new BasketLoader(Some(testResourcePath)) + + Scenario("Can successfully load and parse basket constituents") { + + val constituents = basketLoader.loadConstituents(".FTSE100") + + assert(constituents.length == 3) + val firstRow = constituents.head + assert(firstRow("Symbol") == "AAL.L") + assert(firstRow("Last Trade") == "436.35") + assert(firstRow("Name") == "Anglo American PLC") + assert(firstRow("Weighting") == 0.0278736825813547) + assert(firstRow("Volume") == "5799089") + assert(firstRow("Change") == "5.35") + } + + Scenario("When parsing basket constituents fails return empty") { + + val constituents = basketLoader.loadConstituents(".FTSEWithError") + + assert(constituents.length == 0) + } + + + Scenario("When no matching basket constituents file return empty") { + + val constituents = basketLoader.loadConstituents(".NoSuchFile") + + assert(constituents.length == 0) + } + + } +} \ No newline at end of file diff --git a/example/main-java/pom.xml b/example/main-java/pom.xml index 6f9014449..7e1e2f1b3 100644 --- a/example/main-java/pom.xml +++ b/example/main-java/pom.xml @@ -19,6 +19,15 @@ 0.9.36-SNAPSHOT + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + tests + test-jar + test + + org.finos.vuu basket diff --git a/example/main-java/src/main/java/org/finos/vuu/module/MyExampleModule.java b/example/main-java/src/main/java/org/finos/vuu/module/MyExampleModule.java index 188ac9ffa..2d3d441ff 100644 --- a/example/main-java/src/main/java/org/finos/vuu/module/MyExampleModule.java +++ b/example/main-java/src/main/java/org/finos/vuu/module/MyExampleModule.java @@ -14,7 +14,7 @@ public class MyExampleModule extends DefaultModule { - private final String NAME = "MY_MOD"; + public static final String NAME = "MY_MOD"; public ViewServerModule create(final TableDefContainer tableDefContainer){ return ModuleFactory.withNamespace(NAME, tableDefContainer) diff --git a/example/main-java/src/test/java/org/finos/vuu/JavaTestExample.java b/example/main-java/src/test/java/org/finos/vuu/JavaTestExample.java new file mode 100644 index 000000000..617a5e29d --- /dev/null +++ b/example/main-java/src/test/java/org/finos/vuu/JavaTestExample.java @@ -0,0 +1,60 @@ +package org.finos.vuu; + +import org.finos.toolbox.jmx.MetricsProvider; +import org.finos.toolbox.jmx.MetricsProviderImpl; +import org.finos.toolbox.lifecycle.LifecycleContainer; +import org.finos.toolbox.time.Clock; +import org.finos.toolbox.time.TestFriendlyClock; +import org.finos.vuu.core.module.TableDefContainer; +import org.finos.vuu.core.module.ViewServerModule; +import org.finos.vuu.module.MyExampleModule; +import org.finos.vuu.provider.MockProvider; +import org.finos.vuu.test.VuuServerTestCase; +import org.finos.vuu.viewport.ViewPort; +import org.scalatest.Ignore; +import scala.collection.immutable.Seq; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import static scala.jdk.javaapi.CollectionConverters.asScala; + +public class JavaTestExample extends VuuServerTestCase { + + public static Seq toScalaSeq(ViewServerModule... modules){ + return new scala.collection.mutable.ListBuffer().addAll(asScala(Arrays.stream(modules).collect(Collectors.toList()))).toSeq(); + } + + + @Ignore + public void testVuuServerFunctionality() throws Exception{ + + final MetricsProvider metrics = new MetricsProviderImpl(); + final Clock clock = new TestFriendlyClock(1000000000000L); + final LifecycleContainer lifecycle = new LifecycleContainer(clock); + final TableDefContainer tableDefContainer = new TableDefContainer(); + + final ViewServerModule module = new MyExampleModule().create(tableDefContainer); + + withVuuServer(toScalaSeq(module), (vuuServer) -> { + + vuuServer.login("test", "test"); + + ViewPort viewport = vuuServer.createViewPort(MyExampleModule.NAME, "myTable"); + + MockProvider provider = vuuServer.getProvider(MyExampleModule.NAME, "myTable"); + +// provider.tick("123", Map.of("id", "123", "foo", "bar", "myInt", 123)); +// +// Seq updates = combineQs(viewport); +// +// assertVpEq(updates, () -> asList( +// asList("id", "foo", "myInt"), +// asList("123", "bar", 123) +// )); + + return null; + }, clock, lifecycle, metrics); + } + +} diff --git a/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala index 5d08aee37..9b0be7bbf 100644 --- a/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala +++ b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala @@ -291,7 +291,7 @@ class ParentChildOrdersModel(implicit clock: Clock, lifecycleContainer: Lifecycl val instIdx = randomNumbers.seededRand(0, instruments.length - 1) val instrument = instruments(instIdx) val quantity = randomNumbers.seededRand(0, 30) * 100 + randomNumbers.seededRand(0, 100) - val side = if (randomNumbers.seededRand(0, 10) > 8) "Buy" else "Sell" + val side = if (randomNumbers.seededRand(0, 10) > 8) "BUY" else "SELL" val account = accounts(randomNumbers.seededRand(0, accounts.length - 1)) val algo = algos(randomNumbers.seededRand(0, algos.length - 1)) val volLimit = randomNumbers.seededRand(0, 10) * 10 diff --git a/example/order/src/main/scala/org/finos/vuu/order/oms/OmsApi.scala b/example/order/src/main/scala/org/finos/vuu/order/oms/OmsApi.scala index 12a15fdac..a780c854a 100644 --- a/example/order/src/main/scala/org/finos/vuu/order/oms/OmsApi.scala +++ b/example/order/src/main/scala/org/finos/vuu/order/oms/OmsApi.scala @@ -23,6 +23,7 @@ trait OmsApi { def addListener(omsListener: OmsListener): Unit def runOnce(): Unit def containsOrder(clientOrderId: String): Boolean + def getOrderId(clientOrderId: String): Option[Int] } trait OmsListener{ diff --git a/example/order/src/main/scala/org/finos/vuu/order/oms/impl/InMemOmsApi.scala b/example/order/src/main/scala/org/finos/vuu/order/oms/impl/InMemOmsApi.scala index 1805f5a9b..09b4ac4c2 100644 --- a/example/order/src/main/scala/org/finos/vuu/order/oms/impl/InMemOmsApi.scala +++ b/example/order/src/main/scala/org/finos/vuu/order/oms/impl/InMemOmsApi.scala @@ -42,7 +42,13 @@ class InMemOmsApi(implicit val clock: Clock) extends OmsApi { override def replaceOrder(replaceOrder: ReplaceOrder): Unit = ??? - override def cancelOrder(cancelOrder: CancelOrder): Unit = ??? + override def cancelOrder(cancelOrder: CancelOrder): Unit = { + orders = orders.map(orderState => + if (orderState.orderId == cancelOrder.orderId) + orderState.copy(state = States.CANCELLED, nextEventTime = clock.now()) + else orderState + ) + } override def addListener(omsListener: OmsListener): Unit = listeners = listeners ++ List(omsListener) @@ -58,9 +64,14 @@ class InMemOmsApi(implicit val clock: Clock) extends OmsApi { orderstate.copy(state = States.ACKED, nextEventTime = clock.now() + random.between(1000, MaxTimes.MAX_FILL_TIME_MS), orderId = orderId) case 'A' => val remainingQty = orderstate.qty - orderstate.filledQty - val fillQty = if(remainingQty > 1) random.between(1, orderstate.qty - orderstate.filledQty) else 1 - listeners.foreach(_.onFill(Fill(orderstate.orderId, fillQty, orderstate.price, orderstate.clientOrderId, orderstate.filledQty + fillQty, orderstate.qty))) - orderstate.copy(filledQty = orderstate.filledQty + fillQty, nextEventTime = clock.now() + random.between(1000, 5000)) + val fillQty = if(remainingQty > 1) random.between(1, remainingQty) else 1 + val totalFilledQty = orderstate.filledQty + fillQty + val nextState = if( orderstate.qty == totalFilledQty) States.FILLED else States.ACKED + listeners.foreach(_.onFill(Fill(orderstate.orderId, fillQty, orderstate.price, orderstate.clientOrderId, totalFilledQty, orderstate.qty))) + orderstate.copy(state = nextState, filledQty = totalFilledQty, nextEventTime = clock.now() + random.between(1000, MaxTimes.MAX_FILL_TIME_MS)) + case 'X' => + listeners.foreach(_.onCancelAck(CancelAck(orderstate.orderId, orderstate.clientOrderId))) + orderstate case _ => orderstate } @@ -70,8 +81,14 @@ class InMemOmsApi(implicit val clock: Clock) extends OmsApi { } }) - orders = orders.filter(os => os.filledQty != os.qty) + orders = orders.filter(os => os.state != States.FILLED && os.state != States.CANCELLED) } + override def getOrderId(clientOrderId: String): Option[Int] = { + orders.find(os => os.clientOrderId == clientOrderId) match { + case Some(os) => Some(os.orderId) + case None => None + } + } } diff --git a/example/order/src/test/scala/org/finos/vuu/order/oms/OmsApiTest.scala b/example/order/src/test/scala/org/finos/vuu/order/oms/OmsApiTest.scala index e3e2b54f5..eb2ed2454 100644 --- a/example/order/src/test/scala/org/finos/vuu/order/oms/OmsApiTest.scala +++ b/example/order/src/test/scala/org/finos/vuu/order/oms/OmsApiTest.scala @@ -62,7 +62,7 @@ class OmsApiTest extends AnyFeatureSpec with GivenWhenThen with Matchers { omsApi.addListener(listener) - omsApi.createOrder(NewOrder("Buy","VOD.L", 1000L, 100.01, "clOrdId1")) + omsApi.createOrder(NewOrder("BUY","VOD.L", 1000L, 100.01, "clOrdId1")) clock.sleep(MAX_ACK_TIME_MS) omsApi.runOnce() @@ -74,7 +74,7 @@ class OmsApiTest extends AnyFeatureSpec with GivenWhenThen with Matchers { omsApi.containsOrder("clOrdId1") should equal(true) - listener.getOrderState("clOrdId1").get.filledQty should be > (0L) + listener.getOrderState("clOrdId1").get.filledQty should be > 0L for (n <- 1 to 1000) { clock.sleep(MAX_FILL_TIME_MS) @@ -84,5 +84,34 @@ class OmsApiTest extends AnyFeatureSpec with GivenWhenThen with Matchers { omsApi.containsOrder("clOrdId1") should equal(false) } + + Scenario("Check we can submit order and cancel") { + + implicit val clock: Clock = new TestFriendlyClock(1000L) + + val omsApi = OmsApi() + + val listener = new TestListener() + + omsApi.addListener(listener) + + omsApi.createOrder(NewOrder("BUY", "VOD.L", 1000L, 100.01, "clOrdId1")) + omsApi.createOrder(NewOrder("BUY", "BP.L", 1000L, 150.01, "clOrdId2")) + + clock.sleep(MAX_ACK_TIME_MS) + omsApi.runOnce() + + listener.getOrderState("clOrdId1").get.state should equal("ACKED") + + val orderId = omsApi.getOrderId("clOrdId1").get + omsApi.cancelOrder(CancelOrder(orderId)) + omsApi.runOnce() + + omsApi.containsOrder("clOrdId1") should equal(false) + listener.getOrderState("clOrdId1").get.state should equal("CANCELLED") + + omsApi.containsOrder("clOrdId2") should equal(true) + + } } } diff --git a/example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala b/example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala index 6ed0f410a..23e6f114d 100644 --- a/example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala +++ b/example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala @@ -89,8 +89,8 @@ class SimulatedPricesProvider(val table: DataTable, @volatile var maxSleep: Int val maxBidValue = maxBid(bid, tempAsk, spreadMultipler, priceMaxDelta) val minAskValue = minAsk(bid, tempAsk, spreadMultipler, priceMaxDelta) val maxAskValue = maxAsk(bid, tempAsk, spreadMultipler, priceMaxDelta) - val newBid = (nextRandomDouble(minBidValue, maxBidValue) * 100).round / 100.0 - val newAsk = (nextRandomDouble(minAskValue, maxAskValue) * 100).round / 100.0 + val newBid = round(nextRandomDouble(minBidValue, maxBidValue)) + val newAsk = round(nextRandomDouble(minAskValue, maxAskValue)) (newBid, newAsk) } @@ -252,8 +252,8 @@ class SimulatedPricesProvider(val table: DataTable, @volatile var maxSleep: Int val tempBid = nextRandomDouble(mid - priceMaxDelta, mid - 1) val ask = nextRandomDouble(mid + 1, mid + priceMaxDelta) val bid = if (tempBid < 0) mid else tempBid - val newBid = (bid * 100).round / 100.0 - val newAsk = (ask * 100).round / 100.0 + val newBid = round(bid) + val newAsk = round(ask) (newBid, newAsk) } protected def buildSampleRow(ric: String): Map[String, Any] = { @@ -261,10 +261,10 @@ class SimulatedPricesProvider(val table: DataTable, @volatile var maxSleep: Int Map(f.Ric -> ric, f.Ask -> ask, f.Bid -> bid, f.Phase -> "C") ++ BidAskSize() } - final val MaxSpread = 100 + final val MaxSpread = 10 protected def doWidenBidAndAsk(ric: String): Map[String, Any] = { - if (!states.get(ric).contains(ric)) { + if (!states.get(ric).contains(f.Bid)) { seedStartValues(ric) } else { getState(ric) match { @@ -277,8 +277,8 @@ class SimulatedPricesProvider(val table: DataTable, @volatile var maxSleep: Int else spread - val newBid = bid - activeSpread - val newAsk = ask + activeSpread + val newBid = round(bid - activeSpread) + val newAsk = round(ask + activeSpread) Map(f.Ric -> ric, f.Ask -> newAsk, f.Bid -> newBid, f.Scenario -> "widenBidAndAsk", f.Phase -> "C") ++ BidAskSize() case None => throw new Exception("shouldn't get here") } @@ -293,11 +293,15 @@ class SimulatedPricesProvider(val table: DataTable, @volatile var maxSleep: Int val bid = states.get(ric)(f.Bid).asInstanceOf[Double] val ask = states.get(ric)(f.Ask).asInstanceOf[Double] val (newBid:Double, newAsk:Double) = generateNextBidAsk(bid, ask, 10, 5, nextRandomDouble) - val last = ((ask + (newAsk - ask) / 2) * 100).round / 100.0 + val last = round(ask + (newAsk - ask) / 2) Map(f.Ric -> ric, f.Ask -> newAsk, f.Bid -> newBid, f.Scenario -> "fastTick", f.Last -> last, f.Phase -> "C") ++ BidAskSize() } } + private def round(value: Double): Double = { + (value * 100).round / 100.0 + } + protected def doOpenTick(ric: String): Map[String, Any] = { if (!states.get(ric).contains(f.Bid)) @@ -306,7 +310,7 @@ class SimulatedPricesProvider(val table: DataTable, @volatile var maxSleep: Int val bid = states.get(ric)(f.Bid).asInstanceOf[Double] val ask = states.get(ric)(f.Ask).asInstanceOf[Double] val (newBid: Double, newAsk: Double) = generateNextBidAsk(bid, ask, 8, 4, nextRandomDouble) - val open = ask + (newAsk - ask) / 2 + val open = round(ask + (newAsk - ask) / 2) Map(f.Ric -> ric, f.Scenario -> "open", f.Open -> open, f.Phase -> "O") ++ BidAskSize() } } diff --git a/vuu-ui/.eslintignore b/vuu-ui/.eslintignore index d575a02fe..bc06d2d13 100644 --- a/vuu-ui/.eslintignore +++ b/vuu-ui/.eslintignore @@ -17,4 +17,5 @@ stories storybook-static showcase/dist target -packages/shell/src/feature/Feature.jsx \ No newline at end of file +packages/shell/src/feature/Feature.jsx +**/inlined-worker.js diff --git a/vuu-ui/.eslintrc.json b/vuu-ui/.eslintrc.json index 36e7f7554..5db1aafef 100644 --- a/vuu-ui/.eslintrc.json +++ b/vuu-ui/.eslintrc.json @@ -35,8 +35,11 @@ ], "no-unused-vars": 0, - "prefer-const": ["error", {"destructuring": "all"}], - "@typescript-eslint/no-unused-vars": ["error", { "ignoreRestSiblings": true }] + "prefer-const": ["error", { "destructuring": "all" }], + "@typescript-eslint/no-unused-vars": [ + "warn", + { "ignoreRestSiblings": true, "argsIgnorePattern": "_" } + ] }, "overrides": [ { diff --git a/vuu-ui/cypress.config.ts b/vuu-ui/cypress.config.ts index 978b48e13..d0e74de28 100644 --- a/vuu-ui/cypress.config.ts +++ b/vuu-ui/cypress.config.ts @@ -27,29 +27,6 @@ const viteConfig: UserConfig = { }, }, }; -// if (isCI) { -// viteConfig = mergeConfig(viteConfig, { -// resolve: { -// alias: { -// "@salt-ds/core": path.resolve(__dirname, "./dist/salt-ds-core"), -// "@salt-ds/data-grid": path.resolve( -// __dirname, -// "./dist/salt-ds-data-grid" -// ), -// "@salt-ds/lab": path.resolve(__dirname, "./dist/salt-ds-lab"), -// "@salt-ds/icons": path.resolve(__dirname, "./dist/salt-ds-icons"), -// }, -// }, -// optimizeDeps: { -// include: [ -// "@salt-ds/core", -// "@salt-ds/data-grid", -// "@salt-ds/lab", -// "@salt-ds/icons", -// ], -// }, -// } as UserConfig); -// } export default defineConfig({ viewportWidth: 1280, @@ -78,10 +55,17 @@ export default defineConfig({ }, e2e: { - baseUrl: "http://127.0.0.1:5173/", + baseUrl: "http://localhost:4173/", // eslint-disable-next-line @typescript-eslint/no-unused-vars setupNodeEvents(on, config) { // implement node event listeners here + on("task", { + log(message: string) { + console.log(message); + + return null; + }, + }); }, chromeWebSecurity: false, defaultCommandTimeout: 10000, diff --git a/vuu-ui/cypress/e2e/layout-management/screenshot.cy.js b/vuu-ui/cypress/e2e/layout-management/screenshot.cy.js deleted file mode 100644 index db03b177b..000000000 --- a/vuu-ui/cypress/e2e/layout-management/screenshot.cy.js +++ /dev/null @@ -1,29 +0,0 @@ -import "cypress-iframe"; -import { SHELL_WITH_NEW_THEME_URL } from "../../support/e2e/constants"; - -context("Screenshot", () => { - beforeEach(() => { - cy.visit(SHELL_WITH_NEW_THEME_URL); - }); - - // TODO (#VUU24): Improve test alignment with the user flow - it("Takes a screenshot of the current layout and displays it in the save layout dialog", () => { - // TODO (#VUU24): Improve selector - cy.get("#tab1-tab").then((tab) => { - cy.wrap(tab).findByRole("button").click(); - }); - - // TODO (#VUU24): Improve selector - cy.findByRole("menuitem", { name: "Save Layout" }).click(); - - // TODO (#VUU24): Don't find by classname, use an accessible selector - cy.get(".saveLayoutPanel-panelContainer").then((dialog) => { - cy.wrap(dialog) - .find("img") - .should("be.visible") - .and(($img) => { - expect($img[0].naturalWidth).to.be.greaterThan(0); - }); - }); - }); -}); diff --git a/vuu-ui/cypress/e2e/layout-management/screenshot.cy.ts b/vuu-ui/cypress/e2e/layout-management/screenshot.cy.ts new file mode 100644 index 000000000..6a72c3cbc --- /dev/null +++ b/vuu-ui/cypress/e2e/layout-management/screenshot.cy.ts @@ -0,0 +1,25 @@ +import "cypress-iframe"; +import { ShellWithNewTheme } from "../../pages/ShellWithNewTheme"; +import { SaveLayoutDialog } from "../../pages/SaveLayoutDialog"; + +const page = new ShellWithNewTheme(); +const dialog = new SaveLayoutDialog(); + +context("Screenshot", () => { + beforeEach(() => { + page.visit(); + }); + + it("Takes a screenshot of the current layout and displays it in the save layout dialog", () => { + page.getContextMenuButton().click(); + page.getSaveLayoutButton().click(); + + dialog + .getScreenshot() + .should("be.visible") + .and(($img: JQuery) => { + const img = $img[0] as HTMLImageElement; + expect(img.naturalWidth).to.be.greaterThan(0); + }); + }); +}); diff --git a/vuu-ui/cypress/pages/SaveLayoutDialog.ts b/vuu-ui/cypress/pages/SaveLayoutDialog.ts new file mode 100644 index 000000000..282c15d2b --- /dev/null +++ b/vuu-ui/cypress/pages/SaveLayoutDialog.ts @@ -0,0 +1,21 @@ +export class SaveLayoutDialog { + getScreenshot: () => Cypress.Chainable> = () => { + return cy.findByAltText("screenshot of current layout"); + } + + getGroupField: () => Cypress.Chainable> = () => { + return cy.findByRole("combobox", { name: "Group" }); + } + + getNameField: () => Cypress.Chainable> = () => { + return cy.findByRole("textbox", { name: "Layout Name" }); + } + + getSaveButton: () => Cypress.Chainable> = () => { + return cy.findByRole("dialog").findByRole("button", { name: "Save" }); + } + + getCancelButton: () => Cypress.Chainable> = () => { + return cy.findByRole("dialog").findByRole("button", { name: "Cancel" }); + } +} diff --git a/vuu-ui/cypress/pages/ShellWithNewTheme.ts b/vuu-ui/cypress/pages/ShellWithNewTheme.ts new file mode 100644 index 000000000..6195346b0 --- /dev/null +++ b/vuu-ui/cypress/pages/ShellWithNewTheme.ts @@ -0,0 +1,45 @@ +import { formatDate } from "@finos/vuu-utils"; +import { SHELL_WITH_NEW_THEME_URL } from "../support/e2e/constants"; + +export class ShellWithNewTheme { + visit: () => void = () => { + cy.visit(SHELL_WITH_NEW_THEME_URL); + }; + + getContextMenuButton: () => Cypress.Chainable> = () => { + return cy + .findByRole("tablist", { name: "data tabs" }) + .findAllByRole("tab") + .first() + .findByRole("button", { name: "context menu" }); + }; + + getSaveLayoutButton: () => Cypress.Chainable> = () => { + return cy.findByRole("menuitem", { name: "Save Layout" }); + }; + + getMyLayoutsButton: () => Cypress.Chainable> = () => { + return cy.findByRole("tab", { name: "MY LAYOUTS" }); + }; + + getLayoutTile: ( + layoutName: string, + group: string, + creator: string, + date: Date + ) => Cypress.Chainable> = ( + layoutName: string, + group: string, + creator: string, + date: Date + ) => { + const formattedDate = formatDate({ date: "dd.mm.yyyy" })(date); + const layoutTileName = `${layoutName} ${creator}, ${formattedDate}`; + + return cy + .findByRole("listbox", { name: "my layouts" }) + .findByRole("list", { name: group }) + .findByRole("listitem", { name: layoutTileName }) + .findByRole("button"); + }; +} diff --git a/vuu-ui/cypress/support/component/assertions.ts b/vuu-ui/cypress/support/component/assertions.ts index c3a2bfd1a..9b3916653 100644 --- a/vuu-ui/cypress/support/component/assertions.ts +++ b/vuu-ui/cypress/support/component/assertions.ts @@ -102,7 +102,7 @@ declare global { * @example * cy.findByRole('option).should('be.highlighted') */ -const isHighlighted: ChaiPlugin = (_chai, utils) => { +const isHighlighted: ChaiPlugin = (_chai) => { function assertIsHighlighted(this: AssertionStatic) { const root = this._obj.get(0); // make sure it's an Element @@ -134,7 +134,7 @@ chai.use(isHighlighted); * @example * cy.findByRole('option).should('have.focusVisible') */ -const hasFocusVisible: ChaiPlugin = (_chai, utils) => { +const hasFocusVisible: ChaiPlugin = (_chai) => { function assertHasFocusVisible(this: AssertionStatic) { const root = this._obj.get(0); // make sure it's an Element @@ -166,7 +166,7 @@ chai.use(hasFocusVisible); * @example * cy.findByRole('option).should('be.highlighted') */ -const hasAriaSelected: ChaiPlugin = (_chai, utils) => { +const hasAriaSelected: ChaiPlugin = (_chai) => { function assertHasAriaSelected(this: AssertionStatic) { const root = this._obj.get(0); // make sure it's an Element diff --git a/vuu-ui/cypress/support/component/commands.tsx b/vuu-ui/cypress/support/component/commands.tsx index 419c6bb64..49b69a9c3 100644 --- a/vuu-ui/cypress/support/component/commands.tsx +++ b/vuu-ui/cypress/support/component/commands.tsx @@ -5,7 +5,7 @@ import "cypress-axe"; import { Options } from "cypress-axe"; // import { PerformanceResult, PerformanceTester } from "./PerformanceTester"; import { ReactNode } from "react"; -import { ThemeProvider } from "@finos/vuu-shell"; +import { ThemeProvider } from "@finos/vuu-utils"; const SupportedThemeModeValues = ["light", "dark"] as const; type SupportedThemeMode = (typeof SupportedThemeModeValues)[number]; diff --git a/vuu-ui/cypress/tsconfig.json b/vuu-ui/cypress/tsconfig.json index 8f4e0883e..6f53146a4 100644 --- a/vuu-ui/cypress/tsconfig.json +++ b/vuu-ui/cypress/tsconfig.json @@ -6,5 +6,5 @@ "./support" ] }, - "include": ["**/*.tsx", "../cypress.d.ts"] + "include": ["**/*.ts", "**/*.tsx", "../cypress.d.ts"] } diff --git a/vuu-ui/package-lock.json b/vuu-ui/package-lock.json index ead0139b7..3ebf832de 100644 --- a/vuu-ui/package-lock.json +++ b/vuu-ui/package-lock.json @@ -14,17 +14,16 @@ "showcase" ], "dependencies": { + "@salt-ds/core": "1.13.2", "@types/jest": "^26.0.20", - "@types/node": "^14.14.35", + "@types/node": "^18.0.0", "@types/react": "^17.0.2", "@types/react-dom": "^17.0.2", "@typescript-eslint/parser": "^5.41.0", - "classnames": "^2.3.1", - "clsx": "^1.2.1", + "clsx": "^2.0.0", "html-to-image": "^1.11.11", "react": "^17.0.2", "react-dom": "^17.0.2", - "recoil": "^0.1.3", "semver": "^7.5.2" }, "bin": { @@ -33,18 +32,18 @@ "devDependencies": { "@heswell/component-anatomy": "0.0.5", "@lezer/generator": "^1.2.2", - "@testing-library/cypress": "^9.0.0", + "@testing-library/cypress": "10.0.1", "@types/jsdom": "^21.1.2", - "@types/testing-library__cypress": "^5.0.9", + "@types/testing-library__cypress": "5.0.13", "@typescript-eslint/eslint-plugin": "^5.41.0", - "@vitejs/plugin-react": "^4.0.2", + "@vitejs/plugin-react": "4.2.1", "chalk": "^5.2.0", - "cypress": "^12.3.0", - "cypress-axe": "^1.2.0", - "cypress-iframe": "^1.0.1", - "cypress-real-events": "^1.7.6", - "esbuild": "0.17.18", - "esbuild-visualizer": "^0.4.0", + "cypress": "13.6.1", + "cypress-axe": "1.5.0", + "cypress-iframe": "1.0.1", + "cypress-real-events": "1.11.0", + "esbuild": "0.19.10", + "esbuild-visualizer": "0.5.1", "eslint": "8.36.0", "eslint-config-prettier": "8.7.0", "eslint-plugin-cypress": "^2.13.3", @@ -52,14 +51,15 @@ "eslint-plugin-react": "7.32.2", "eslint-plugin-react-hooks": "4.6.0", "happy-dom": "^10.10.0", - "open": "^8.4.0", + "open": "10.0.0", "prettier": "2.8.4", + "serve": "^14.2.1", "stylelint": "^15.0.0", "tinycolor2": "1.4.2", "typescript": "4.9.5", - "vite": "4.5.0", - "vite-tsconfig-paths": "^4.0.3", - "vitest": "0.34.6" + "vite": "5.0.10", + "vite-tsconfig-paths": "4.2.2", + "vitest": "1.1.0" }, "engines": { "node": ">=16.0.0" @@ -87,12 +87,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.10", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -156,34 +156,34 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", - "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", + "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-compilation-targets": "^7.22.10", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.10", - "@babel/parser": "^7.22.10", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.6", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { @@ -204,12 +204,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", - "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "@babel/types": "^7.22.10", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -219,14 +219,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", - "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -244,22 +244,22 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -278,28 +278,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -342,53 +342,53 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", - "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", + "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, @@ -453,9 +453,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", - "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -465,9 +465,9 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz", - "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -480,9 +480,9 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz", - "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -519,34 +519,34 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", - "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", + "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.10", - "@babel/types": "^7.22.10", - "debug": "^4.1.0", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -554,13 +554,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", - "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -720,9 +720,9 @@ } }, "node_modules/@cypress/request": { - "version": "2.88.12", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.12.tgz", - "integrity": "sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", @@ -738,7 +738,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "~6.10.3", + "qs": "6.10.4", "safe-buffer": "^5.1.2", "tough-cookie": "^4.1.3", "tunnel-agent": "^0.6.0", @@ -772,10 +772,26 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz", + "integrity": "sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", - "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", + "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", "cpu": [ "arm" ], @@ -789,9 +805,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", - "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", + "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", "cpu": [ "arm64" ], @@ -805,9 +821,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", - "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", + "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", "cpu": [ "x64" ], @@ -821,9 +837,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", - "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", + "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", "cpu": [ "arm64" ], @@ -837,9 +853,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", - "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", + "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", "cpu": [ "x64" ], @@ -853,9 +869,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", - "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", + "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", "cpu": [ "arm64" ], @@ -869,9 +885,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", - "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", + "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", "cpu": [ "x64" ], @@ -885,9 +901,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", - "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", + "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", "cpu": [ "arm" ], @@ -901,9 +917,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", - "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", + "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", "cpu": [ "arm64" ], @@ -917,9 +933,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", - "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", + "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", "cpu": [ "ia32" ], @@ -933,9 +949,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", - "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", + "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", "cpu": [ "loong64" ], @@ -949,9 +965,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", - "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", + "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", "cpu": [ "mips64el" ], @@ -965,9 +981,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", - "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", + "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", "cpu": [ "ppc64" ], @@ -981,9 +997,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", - "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", + "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", "cpu": [ "riscv64" ], @@ -997,9 +1013,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", - "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", + "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", "cpu": [ "s390x" ], @@ -1013,9 +1029,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", - "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", + "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", "cpu": [ "x64" ], @@ -1029,9 +1045,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", - "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", + "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", "cpu": [ "x64" ], @@ -1045,9 +1061,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", - "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", + "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", "cpu": [ "x64" ], @@ -1061,9 +1077,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", - "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", + "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", "cpu": [ "x64" ], @@ -1077,9 +1093,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", - "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", + "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", "cpu": [ "arm64" ], @@ -1093,9 +1109,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", - "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", + "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", "cpu": [ "ia32" ], @@ -1109,9 +1125,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", - "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", + "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", "cpu": [ "x64" ], @@ -1232,10 +1248,18 @@ "resolved": "packages/vuu-data-ag-grid", "link": true }, + "node_modules/@finos/vuu-data-local": { + "resolved": "packages/vuu-data-local", + "link": true + }, "node_modules/@finos/vuu-data-react": { "resolved": "packages/vuu-data-react", "link": true }, + "node_modules/@finos/vuu-data-remote": { + "resolved": "packages/vuu-data-remote", + "link": true + }, "node_modules/@finos/vuu-data-test": { "resolved": "packages/vuu-data-test", "link": true @@ -1244,10 +1268,6 @@ "resolved": "packages/vuu-data-types", "link": true }, - "node_modules/@finos/vuu-datagrid": { - "resolved": "packages/vuu-datagrid", - "link": true - }, "node_modules/@finos/vuu-datatable": { "resolved": "packages/vuu-datatable", "link": true @@ -1662,9 +1682,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1792,14 +1812,183 @@ "node": ">=14" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz", + "integrity": "sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz", + "integrity": "sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz", + "integrity": "sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz", + "integrity": "sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz", + "integrity": "sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz", + "integrity": "sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz", + "integrity": "sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz", + "integrity": "sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz", + "integrity": "sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz", + "integrity": "sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz", + "integrity": "sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz", + "integrity": "sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz", + "integrity": "sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@salt-ds/core": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@salt-ds/core/-/core-1.8.0.tgz", - "integrity": "sha512-Na8/PEQdb93i6UvYeIn6PhLqjF3k7EbAI+/4zkHO/XeqCBGkRxK3EMibEPkw4Zwfw5PQZbDKgPxknW53aWP0AA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@salt-ds/core/-/core-1.13.2.tgz", + "integrity": "sha512-dBw4QErYpNgfj0wL2kKeZtdoiRXS6ZFgXHSh37yBHrP/QIqFNmhwCAWGR84OgNgetU6FhKvKSSgknwyHAK0fcg==", "dependencies": { "@floating-ui/react": "^0.23.0", - "@salt-ds/icons": "^1.6.0", - "@salt-ds/styles": "^0.1.1", + "@salt-ds/icons": "^1.9.0", + "@salt-ds/styles": "^0.2.0", "@salt-ds/window": "^0.1.1", "clsx": "^2.0.0" }, @@ -1815,11 +2004,11 @@ } }, "node_modules/@salt-ds/core/node_modules/@salt-ds/icons": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@salt-ds/icons/-/icons-1.6.0.tgz", - "integrity": "sha512-/9c1L5LyU5cPxaYDyywDu8VnpvOvnaDmuLr/BWLEdyzxSzXTDfcIPtSgpaSaPadubvnnE9mhXdNknLyTqjNXZg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@salt-ds/icons/-/icons-1.9.0.tgz", + "integrity": "sha512-82PnI/9KStt/owSTV/+vxH5AkJaYDEKuJrBbzeC2axxipv8ydbToTaCn6usLOSTm9CQ04rzMFPNcWQSpGUHtjA==", "dependencies": { - "@salt-ds/styles": "^0.1.1", + "@salt-ds/styles": "^0.2.0", "@salt-ds/window": "^0.1.1", "clsx": "^2.0.0" }, @@ -1834,23 +2023,10 @@ } } }, - "node_modules/@salt-ds/core/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@salt-ds/icons": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@salt-ds/icons/-/icons-1.5.1.tgz", - "integrity": "sha512-yBWRk3hcmYKrPTPQTvJsg4K3TBIvtoznaVIeYj8Gg6zy14s4gUN9N4PH9xix0pNgyCFGgluHUTiUKG6AcyGVkA==", - "dependencies": { - "@salt-ds/styles": "^0.1.1", - "@salt-ds/window": "^0.1.1", - "clsx": "^2.0.0" - }, + "node_modules/@salt-ds/core/node_modules/@salt-ds/styles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@salt-ds/styles/-/styles-0.2.0.tgz", + "integrity": "sha512-tPd/XK1PFkPkBsYwh4fhDbo997eaev6row9aaz/sPM0FpEpU8nbvQRhxtr8iA/S4Q5hCj0xrk/jGTuK40V13oQ==", "peerDependencies": { "@types/react": ">=16.14.0", "react": ">=16.14.0", @@ -1862,14 +2038,6 @@ } } }, - "node_modules/@salt-ds/icons/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" - } - }, "node_modules/@salt-ds/lab": { "version": "1.0.0-alpha.15", "resolved": "https://registry.npmjs.org/@salt-ds/lab/-/lab-1.0.0-alpha.15.tgz", @@ -1925,14 +2093,6 @@ } } }, - "node_modules/@salt-ds/lab/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" - } - }, "node_modules/@salt-ds/styles": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@salt-ds/styles/-/styles-0.1.1.tgz", @@ -1983,26 +2143,26 @@ } }, "node_modules/@testing-library/cypress": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-9.0.0.tgz", - "integrity": "sha512-c1XiCGeHGGTWn0LAU12sFUfoX3qfId5gcSE2yHode+vsyHDWraxDPALjVnHd4/Fa3j4KBcc5k++Ccy6A9qnkMA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-10.0.1.tgz", + "integrity": "sha512-e8uswjTZIBhaIXjzEcrQQ8nHRWHgZH7XBxKuIWxZ/T7FxfWhCR48nFhUX5nfPizjVOKSThEfOSv67jquc1ASkw==", "dev": true, "dependencies": { "@babel/runtime": "^7.14.6", - "@testing-library/dom": "^8.1.0" + "@testing-library/dom": "^9.0.0" }, "engines": { "node": ">=12", "npm": ">=6" }, "peerDependencies": { - "cypress": "^12.0.0" + "cypress": "^12.0.0 || ^13.0.0" } }, "node_modules/@testing-library/dom": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", - "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", + "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", @@ -2015,7 +2175,7 @@ "pretty-format": "^27.0.2" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/@testing-library/dom/node_modules/ansi-styles": { @@ -2082,14 +2242,12 @@ "node_modules/@thomaschaplin/cusip-generator": { "version": "1.0.22", "resolved": "https://registry.npmjs.org/@thomaschaplin/cusip-generator/-/cusip-generator-1.0.22.tgz", - "integrity": "sha512-162DBgkPGQI0otk/aW8z7XjyYM1fEOUf+p4yiEgJZhKupSWuwSNcsIcAi4fDZvP/XkI/pBF83aXUlYkWFMqA2Q==", - "dev": true + "integrity": "sha512-162DBgkPGQI0otk/aW8z7XjyYM1fEOUf+p4yiEgJZhKupSWuwSNcsIcAi4fDZvP/XkI/pBF83aXUlYkWFMqA2Q==" }, "node_modules/@thomaschaplin/isin-generator": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@thomaschaplin/isin-generator/-/isin-generator-1.0.3.tgz", "integrity": "sha512-M1vm7MsTdLhOybs21dR1M0/aUAwpM2B7qZvcVMTzxBxnjzwaqCr1EtxMUjecCOoxViIA6A/HO7emlfKUGODBNQ==", - "dev": true, "dependencies": { "@thomaschaplin/cusip-generator": "^1.0.1" } @@ -2115,24 +2273,50 @@ } }, "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true }, - "node_modules/@types/chai": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", - "dev": true + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "node_modules/@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", "dev": true, "dependencies": { - "@types/chai": "*" + "@babel/types": "^7.20.7" } }, "node_modules/@types/cypress": { @@ -2298,9 +2482,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "14.18.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz", - "integrity": "sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==" + "version": "18.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", + "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -2355,9 +2542,9 @@ "dev": true }, "node_modules/@types/testing-library__cypress": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@types/testing-library__cypress/-/testing-library__cypress-5.0.9.tgz", - "integrity": "sha512-WTiIZhZKWDnV+Tgo42pxff8YfHdmaNFQz/bFoTlmfw2vbXcstCcb39VRaRi5yFHj/lb7t3K47btKYEbR1fci+Q==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@types/testing-library__cypress/-/testing-library__cypress-5.0.13.tgz", + "integrity": "sha512-lkxNGVFBEX825Z/FrHA8FLuKv1q5L6Bccqm08Zds2MUG4gd5al32hCpplzVumke3br+hkhtVmuPTfwQadIkc5w==", "dev": true, "dependencies": { "@testing-library/dom": "^7.11.0", @@ -2703,31 +2890,32 @@ } }, "node_modules/@vitejs/plugin-react": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz", - "integrity": "sha512-7wU921ABnNYkETiMaZy7XqpueMnpu5VxvVps13MjmCo+utBdD79sZzrApHawHtVX66cCJQQTXFcjH0y9dSUK8g==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", "dev": true, "dependencies": { - "@babel/core": "^7.22.9", - "@babel/plugin-transform-react-jsx-self": "^7.22.5", - "@babel/plugin-transform-react-jsx-source": "^7.22.5", + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "vite": "^4.2.0" + "vite": "^4.2.0 || ^5.0.0" } }, "node_modules/@vitest/expect": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", - "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.1.0.tgz", + "integrity": "sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w==", "dev": true, "dependencies": { - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", "chai": "^4.3.10" }, "funding": { @@ -2735,13 +2923,13 @@ } }, "node_modules/@vitest/runner": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", - "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.1.0.tgz", + "integrity": "sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw==", "dev": true, "dependencies": { - "@vitest/utils": "0.34.6", - "p-limit": "^4.0.0", + "@vitest/utils": "1.1.0", + "p-limit": "^5.0.0", "pathe": "^1.1.1" }, "funding": { @@ -2749,15 +2937,15 @@ } }, "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dev": true, "dependencies": { "yocto-queue": "^1.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2776,14 +2964,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", - "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.1.0.tgz", + "integrity": "sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ==", "dev": true, "dependencies": { - "magic-string": "^0.30.1", + "magic-string": "^0.30.5", "pathe": "^1.1.1", - "pretty-format": "^29.5.0" + "pretty-format": "^29.7.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2810,26 +2998,26 @@ "dev": true }, "node_modules/@vitest/spy": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", - "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.1.0.tgz", + "integrity": "sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg==", "dev": true, "dependencies": { - "tinyspy": "^2.1.1" + "tinyspy": "^2.2.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", - "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.1.0.tgz", + "integrity": "sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ==", "dev": true, "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2864,6 +3052,12 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/@zeit/schemas": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.29.0.tgz", + "integrity": "sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA==", + "dev": true + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -2872,6 +3066,19 @@ "optional": true, "peer": true }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -2892,9 +3099,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" @@ -2942,6 +3149,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -3010,6 +3226,12 @@ } ] }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3320,13 +3542,138 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/boxen": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", + "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "ansi-align": "^3.0.1", + "camelcase": "^7.0.0", + "chalk": "^5.0.1", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/boxen/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -3341,9 +3688,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -3360,10 +3707,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -3405,6 +3752,30 @@ "node": "*" } }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -3424,13 +3795,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3487,9 +3859,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001519", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz", - "integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "dev": true, "funding": [ { @@ -3552,6 +3924,82 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk-template/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/chalk-template/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -3628,11 +4076,6 @@ "node": ">=8" } }, - "node_modules/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -3642,6 +4085,18 @@ "node": ">=6" } }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3704,6 +4159,67 @@ } ] }, + "node_modules/clipboardy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "dev": true, + "dependencies": { + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clipboardy/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/clipboardy/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clipboardy/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3719,9 +4235,9 @@ } }, "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", "engines": { "node": ">=6" } @@ -3793,6 +4309,57 @@ "node": ">=4.0.0" } }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "node_modules/compute-scroll-into-view": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", @@ -3803,10 +4370,19 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, "node_modules/core-js-pure": { @@ -3925,15 +4501,15 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "node_modules/cypress": { - "version": "12.17.3", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.3.tgz", - "integrity": "sha512-/R4+xdIDjUSLYkiQfwJd630S81KIgicmQOLXotFxVXkl+eTeVO+3bHXxdi5KBh/OgC33HWN33kHX+0tQR/ZWpg==", + "version": "13.6.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.1.tgz", + "integrity": "sha512-k1Wl5PQcA/4UoTffYKKaxA0FJKwg8yenYNYRzLt11CUR0Kln+h7Udne6mdU1cUIdXBDTVZWtmiUjzqGs7/pEpw==", "dev": true, "hasInstallScript": true, "dependencies": { - "@cypress/request": "^2.88.11", + "@cypress/request": "^3.0.0", "@cypress/xvfb": "^1.2.4", - "@types/node": "^16.18.39", + "@types/node": "^18.17.5", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", @@ -3966,6 +4542,7 @@ "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", + "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", "semver": "^7.5.3", @@ -3978,20 +4555,20 @@ "cypress": "bin/cypress" }, "engines": { - "node": "^14.0.0 || ^16.0.0 || >=18.0.0" + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, "node_modules/cypress-axe": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cypress-axe/-/cypress-axe-1.4.0.tgz", - "integrity": "sha512-Ut7NKfzjyKm0BEbt2WxuKtLkIXmx6FD2j0RwdvO/Ykl7GmB/qRQkwbKLk3VP35+83hiIr8GKD04PDdrTK5BnyA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cypress-axe/-/cypress-axe-1.5.0.tgz", + "integrity": "sha512-Hy/owCjfj+25KMsecvDgo4fC/781ccL+e8p+UUYoadGVM2ogZF9XIKbiM6KI8Y3cEaSreymdD6ZzccbI2bY0lQ==", "dev": true, "engines": { "node": ">=10" }, "peerDependencies": { "axe-core": "^3 || ^4", - "cypress": "^10 || ^11 || ^12" + "cypress": "^10 || ^11 || ^12 || ^13" } }, "node_modules/cypress-iframe": { @@ -4004,42 +4581,18 @@ } }, "node_modules/cypress-real-events": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/cypress-real-events/-/cypress-real-events-1.10.0.tgz", - "integrity": "sha512-ALSdCiG+Rj3Sl6qooqTFeFGBxOIe8QJUcgIuJ6ZVBanTEijXRzqxqstMC2ZKfixqj1TyNjolyZU4zOoN/jtHpg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/cypress-real-events/-/cypress-real-events-1.11.0.tgz", + "integrity": "sha512-4LXVRsyq+xBh5TmlEyO1ojtBXtN7xw720Pwb9rEE9rkJuXmeH3VyoR1GGayMGr+Itqf11eEjfDewtDmcx6PWPQ==", "dev": true, - "dependencies": { - "prettier": "^3.0.0" - }, "peerDependencies": { - "cypress": "^4.x || ^5.x || ^6.x || ^7.x || ^8.x || ^9.x || ^10.x || ^11.x || ^12.x" + "cypress": "^4.x || ^5.x || ^6.x || ^7.x || ^8.x || ^9.x || ^10.x || ^11.x || ^12.x || ^13.x" } }, - "node_modules/cypress-real-events/node_modules/prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz", - "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/cypress/node_modules/@types/node": { - "version": "16.18.40", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.40.tgz", - "integrity": "sha512-+yno3ItTEwGxXiS/75Q/aHaa5srkpnJaH+kdkTVJ3DtJEwv92itpKbxU+FjPoh2m/5G9zmUQfrL4A4C13c+iGA==", - "dev": true - }, - "node_modules/cypress/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { "color-convert": "^2.0.1" @@ -4236,15 +4789,15 @@ } }, "node_modules/deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", @@ -4254,16 +4807,28 @@ "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", + "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -4277,13 +4842,58 @@ "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.0.tgz", + "integrity": "sha512-EviRCeDkniKC30N3uKNHIaIsBZEo00ZOrxDZQmJwJeY2q6Uli5SwfmQ6wSf5aezcBS3PDHoQJl/XuAHEfMCJFg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/define-properties": { @@ -4379,6 +4989,12 @@ "node": ">=12" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -4390,9 +5006,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.490", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz", - "integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==", + "version": "1.4.615", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", + "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==", "dev": true }, "node_modules/emoji-regex": { @@ -4558,9 +5174,9 @@ } }, "node_modules/esbuild": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", - "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", + "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", "dev": true, "hasInstallScript": true, "bin": { @@ -4570,44 +5186,72 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.18", - "@esbuild/android-arm64": "0.17.18", - "@esbuild/android-x64": "0.17.18", - "@esbuild/darwin-arm64": "0.17.18", - "@esbuild/darwin-x64": "0.17.18", - "@esbuild/freebsd-arm64": "0.17.18", - "@esbuild/freebsd-x64": "0.17.18", - "@esbuild/linux-arm": "0.17.18", - "@esbuild/linux-arm64": "0.17.18", - "@esbuild/linux-ia32": "0.17.18", - "@esbuild/linux-loong64": "0.17.18", - "@esbuild/linux-mips64el": "0.17.18", - "@esbuild/linux-ppc64": "0.17.18", - "@esbuild/linux-riscv64": "0.17.18", - "@esbuild/linux-s390x": "0.17.18", - "@esbuild/linux-x64": "0.17.18", - "@esbuild/netbsd-x64": "0.17.18", - "@esbuild/openbsd-x64": "0.17.18", - "@esbuild/sunos-x64": "0.17.18", - "@esbuild/win32-arm64": "0.17.18", - "@esbuild/win32-ia32": "0.17.18", - "@esbuild/win32-x64": "0.17.18" + "@esbuild/aix-ppc64": "0.19.10", + "@esbuild/android-arm": "0.19.10", + "@esbuild/android-arm64": "0.19.10", + "@esbuild/android-x64": "0.19.10", + "@esbuild/darwin-arm64": "0.19.10", + "@esbuild/darwin-x64": "0.19.10", + "@esbuild/freebsd-arm64": "0.19.10", + "@esbuild/freebsd-x64": "0.19.10", + "@esbuild/linux-arm": "0.19.10", + "@esbuild/linux-arm64": "0.19.10", + "@esbuild/linux-ia32": "0.19.10", + "@esbuild/linux-loong64": "0.19.10", + "@esbuild/linux-mips64el": "0.19.10", + "@esbuild/linux-ppc64": "0.19.10", + "@esbuild/linux-riscv64": "0.19.10", + "@esbuild/linux-s390x": "0.19.10", + "@esbuild/linux-x64": "0.19.10", + "@esbuild/netbsd-x64": "0.19.10", + "@esbuild/openbsd-x64": "0.19.10", + "@esbuild/sunos-x64": "0.19.10", + "@esbuild/win32-arm64": "0.19.10", + "@esbuild/win32-ia32": "0.19.10", + "@esbuild/win32-x64": "0.19.10" } }, "node_modules/esbuild-visualizer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/esbuild-visualizer/-/esbuild-visualizer-0.4.1.tgz", - "integrity": "sha512-5XI3unzqPr3xqfzR/mzK3LhoAJs3FQhiIXBsKJ3Oh6CjyjuXz6HVmhJMoisrcpeTZip65fR54Dk53MZncA0AUQ==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/esbuild-visualizer/-/esbuild-visualizer-0.5.1.tgz", + "integrity": "sha512-itlh5S2/QqKandylO3C+jANKM/EgNSJNOuT6L14zLWTqsewEPSxlgGunQ5tTWRhlsjON+4S2FZ96a66ItGICnw==", "dev": true, "dependencies": { "open": "^8.4.0", + "picomatch": "^2.3.1", "yargs": "^17.6.2" }, "bin": { "esbuild-visualizer": "dist/bin/cli.js" }, "engines": { - "node": ">=14.20" + "node": ">=18" + } + }, + "node_modules/esbuild-visualizer/node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/esbuild-visualizer/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/escalade": { @@ -5202,6 +5846,21 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dev": true, + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -5410,9 +6069,9 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -5424,10 +6083,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -5484,15 +6146,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5823,6 +6485,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hast-util-to-estree": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", @@ -6324,6 +6998,39 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -6413,6 +7120,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-port-reachable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", + "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -6967,10 +7686,14 @@ } }, "node_modules/local-pkg": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", - "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, "engines": { "node": ">=14" }, @@ -8244,9 +8967,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -8272,6 +8995,15 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/no-scroll": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/no-scroll/-/no-scroll-2.1.1.tgz", @@ -8315,9 +9047,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-package-data": { @@ -8485,6 +9217,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8509,17 +9250,33 @@ } }, "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.0.0.tgz", + "integrity": "sha512-WDekhGCZ7VHBw6sNDzCl42rVL315m/K/A1lYiZO2nHXn9T4yPBXxvrZKYkVPtsCahD815yhFNR9/Wq608PdIaA==", "dev": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "default-browser": "^5.2.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8667,6 +9424,12 @@ "node": ">=0.10.0" } }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -8681,6 +9444,12 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -8765,9 +9534,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "dev": true, "funding": [ { @@ -8784,7 +9553,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -8894,6 +9663,15 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -9001,6 +9779,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -9170,22 +9987,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/recoil": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.1.3.tgz", - "integrity": "sha512-/Rm7wN7jqCjhtFK1TgtK0V115SUXNu6d4QYvwxWNLydib0QChSmpB6U8CaHoRPS0MFWtAIsD/IFjpbfk/OYm7Q==", - "peerDependencies": { - "react": ">=16.13.1" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } - } - }, "node_modules/redent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", @@ -9220,14 +10021,14 @@ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "set-function-name": "^2.0.0" }, "engines": { "node": ">= 0.4" @@ -9236,6 +10037,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "dev": true, + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/remark-mdx": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz", @@ -9390,18 +10213,31 @@ } }, "node_modules/rollup": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", - "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz", + "integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.1", + "@rollup/rollup-android-arm64": "4.9.1", + "@rollup/rollup-darwin-arm64": "4.9.1", + "@rollup/rollup-darwin-x64": "4.9.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.1", + "@rollup/rollup-linux-arm64-gnu": "4.9.1", + "@rollup/rollup-linux-arm64-musl": "4.9.1", + "@rollup/rollup-linux-riscv64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-musl": "4.9.1", + "@rollup/rollup-win32-arm64-msvc": "4.9.1", + "@rollup/rollup-win32-ia32-msvc": "4.9.1", + "@rollup/rollup-win32-x64-msvc": "4.9.1", "fsevents": "~2.3.2" } }, @@ -9421,6 +10257,18 @@ "@babel/runtime": "^7.1.2" } }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -9575,6 +10423,131 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/serve": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.1.tgz", + "integrity": "sha512-48er5fzHh7GCShLnNyPBRPEjs2I6QBozeGr02gaacROiyS/8ARADlj595j39iZXAqBbJHH/ivJJyPRWY9sQWZA==", + "dev": true, + "dependencies": { + "@zeit/schemas": "2.29.0", + "ajv": "8.11.0", + "arg": "5.0.2", + "boxen": "7.0.0", + "chalk": "5.0.1", + "chalk-template": "0.4.0", + "clipboardy": "3.0.0", + "compression": "1.7.4", + "is-port-reachable": "4.0.0", + "serve-handler": "6.1.5", + "update-check": "1.5.4" + }, + "bin": { + "serve": "build/main.js" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dev": true, + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/serve/node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/serve/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9736,9 +10709,9 @@ "dev": true }, "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, "dependencies": { "asn1": "~0.2.3", @@ -9766,10 +10739,14 @@ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, + "node_modules/standalone-table": { + "resolved": "sample-apps/standalone-table", + "link": true + }, "node_modules/std-env": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz", - "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.6.0.tgz", + "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", "dev": true }, "node_modules/stop-iteration-iterator": { @@ -10209,9 +11186,9 @@ "dev": true }, "node_modules/tinybench": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", - "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", + "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", "dev": true }, "node_modules/tinycolor2": { @@ -10223,9 +11200,9 @@ } }, "node_modules/tinypool": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", - "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.1.tgz", + "integrity": "sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==", "dev": true, "engines": { "node": ">=14.0.0" @@ -10514,9 +11491,9 @@ } }, "node_modules/ufo": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz", - "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", "dev": true }, "node_modules/unbox-primitive": { @@ -10534,6 +11511,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unified": { "version": "10.1.2", "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", @@ -10677,9 +11659,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -10706,6 +11688,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/update-check": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", + "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", + "dev": true, + "dependencies": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -10767,6 +11759,15 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -10812,29 +11813,29 @@ } }, "node_modules/vite": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", - "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", + "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", "dev": true, "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", @@ -10867,490 +11868,98 @@ } }, "node_modules/vite-node": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", - "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.1.0.tgz", + "integrity": "sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q==", "dev": true, "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", - "mlly": "^1.4.0", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": ">=v14.18.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite-tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "globrex": "^0.1.2", - "tsconfck": "^2.1.0" - }, - "peerDependencies": { - "vite": "*" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, "engines": { - "node": ">=12" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "node_modules/vite-tsconfig-paths": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.2.tgz", + "integrity": "sha512-dq0FjyxHHDnp0uS3P12WEOX2W7NeuLzX9AWP38D7Zw2CTbFErapwQVlCiT5DMJcVWKQ1MMdTe92PZl/rBQ7qcw==", "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^2.1.0" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "vite": "*" }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, "node_modules/vitest": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", - "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.1.0.tgz", + "integrity": "sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A==", "dev": true, "dependencies": { - "@types/chai": "^4.3.5", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "@vitest/expect": "0.34.6", - "@vitest/runner": "0.34.6", - "@vitest/snapshot": "0.34.6", - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", - "acorn": "^8.9.0", - "acorn-walk": "^8.2.0", + "@vitest/expect": "1.1.0", + "@vitest/runner": "1.1.0", + "@vitest/snapshot": "1.1.0", + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", + "acorn-walk": "^8.3.0", "cac": "^6.7.14", "chai": "^4.3.10", "debug": "^4.3.4", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.1", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "strip-literal": "^1.0.1", - "tinybench": "^2.5.0", - "tinypool": "^0.7.0", - "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", - "vite-node": "0.34.6", + "std-env": "^3.5.0", + "strip-literal": "^1.3.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.1", + "vite": "^5.0.0", + "vite-node": "1.1.0", "why-is-node-running": "^2.2.2" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": ">=v14.18.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@vitest/browser": "*", - "@vitest/ui": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "^1.0.0", + "@vitest/ui": "^1.0.0", "happy-dom": "*", - "jsdom": "*", - "playwright": "*", - "safaridriver": "*", - "webdriverio": "*" + "jsdom": "*" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, + "@types/node": { + "optional": true + }, "@vitest/browser": { "optional": true }, @@ -11362,18 +11971,143 @@ }, "jsdom": { "optional": true - }, - "playwright": { - "optional": true - }, - "safaridriver": { - "optional": true - }, - "webdriverio": { - "optional": true } } }, + "node_modules/vitest/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/vitest/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/vitest/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/vitest/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", @@ -11493,13 +12227,13 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.4", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" @@ -11527,6 +12261,71 @@ "node": ">=8" } }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dev": true, + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -11765,7 +12564,21 @@ "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "react": "^17.0.2" + "react": ">=17.0.2" + } + }, + "packages/vuu-data-local": { + "name": "@finos/vuu-data-local", + "version": "0.0.26", + "license": "Apache-2.0", + "dependencies": { + "@finos/vuu-utils": "0.0.26" + }, + "devDependencies": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" } }, "packages/vuu-data-react": { @@ -11785,13 +12598,31 @@ "@finos/vuu-table-types": "0.0.26" }, "peerDependencies": { - "react": "^17.0.2" + "react": ">=17.0.2" + } + }, + "packages/vuu-data-remote": { + "name": "@finos/vuu-data-remote", + "version": "0.0.26", + "license": "Apache-2.0", + "dependencies": { + "@finos/vuu-filter-parser": "0.0.26", + "@finos/vuu-utils": "0.0.26" + }, + "devDependencies": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" } }, "packages/vuu-data-test": { "name": "@finos/vuu-data-test", "version": "0.0.26", "license": "Apache-2.0", + "dependencies": { + "@thomaschaplin/isin-generator": "1.0.3" + }, "devDependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-table-types": "0.0.26" @@ -11809,6 +12640,7 @@ "packages/vuu-datagrid": { "name": "@finos/vuu-datagrid", "version": "0.0.26", + "extraneous": true, "license": "Apache-2.0", "devDependencies": { "@finos/vuu-filter-types": "0.0.26", @@ -11853,9 +12685,9 @@ "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-filter-parser": { @@ -11886,8 +12718,7 @@ "@finos/vuu-popups": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/lab": "1.0.0-alpha.15", + "@salt-ds/core": "1.13.2", "uuid": "9.0.0" }, "devDependencies": { @@ -11897,8 +12728,8 @@ "@types/uuid": "^9.0.2" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-filters/node_modules/uuid": { @@ -11918,18 +12749,19 @@ "version": "0.0.26", "license": "Apache-2.0", "dependencies": { + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0" + "@salt-ds/core": "1.13.2" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-popups": { @@ -11937,20 +12769,16 @@ "version": "0.0.26", "license": "Apache-2.0", "dependencies": { - "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", - "@finos/vuu-shell": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-protocol-types": { @@ -11971,14 +12799,13 @@ "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2", + "html-to-image": "^1.11.11" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-table": { @@ -11986,22 +12813,21 @@ "version": "0.0.26", "license": "Apache-2.0", "dependencies": { - "@finos/vuu-data": "0.0.26", - "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", - "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2" + }, + "devDependencies": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-table-extras": { @@ -12010,25 +12836,24 @@ "license": "Apache-2.0", "dependencies": { "@finos/vuu-codemirror": "0.0.26", - "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", "@lezer/lr": "1.3.4", - "@salt-ds/core": "1.8.0", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2" }, "devDependencies": { "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-protocol-types": "0.0.26" }, - "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "peerDependencies": { + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-table-extras/node_modules/@lezer/lr": { @@ -12039,6 +12864,7 @@ } }, "packages/vuu-table-types": { + "name": "@finos/vuu-table-types", "version": "0.0.26", "license": "Apache-2.0", "devDependencies": { @@ -12055,19 +12881,18 @@ "version": "0.0.26", "license": "Apache-2.0", "dependencies": { - "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0" + "@salt-ds/core": "1.13.2" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "packages/vuu-utils": { @@ -12075,13 +12900,14 @@ "version": "0.0.26", "license": "Apache-2.0", "devDependencies": { + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-protocol-types": "0.0.26", "@finos/vuu-table-types": "0.0.26" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "sample-apps/app-vuu-basket-trader": { @@ -12120,11 +12946,11 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", "@fontsource/open-sans": "^4.5.13", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15", - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" }, "devDependencies": {}, "engines": { @@ -12137,28 +12963,30 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26", "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", - "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, - "devDependencies": {}, + "devDependencies": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" + }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "sample-apps/feature-filter-table": { @@ -12179,7 +13007,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, "devDependencies": {}, @@ -12187,9 +13015,9 @@ "node": ">=16.0.0" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "sample-apps/feature-instrument-tiles": { @@ -12210,7 +13038,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, "devDependencies": {}, @@ -12218,9 +13046,9 @@ "node": ">=16.0.0" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "sample-apps/feature-template": { @@ -12241,7 +13069,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, "devDependencies": {}, @@ -12249,9 +13077,9 @@ "node": ">=16.0.0" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "sample-apps/feature-vuu-blotter": { @@ -12315,6 +13143,21 @@ "react-dom": "^17.0.2" } }, + "sample-apps/standalone-table": { + "version": "0.0.26", + "license": "Apache-2.0", + "dependencies": { + "@finos/vuu-table": "0.0.26", + "@fontsource/open-sans": "^4.5.13", + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" + }, + "devDependencies": {}, + "engines": { + "node": ">=16.0.0" + } + }, "showcase": { "name": "@finos/showcase", "version": "0.0.26", @@ -12323,18 +13166,15 @@ "@faker-js/faker": "^8.0.2", "@finos/vuu-data-ag-grid": "0.0.26", "@finos/vuu-data-test": "0.0.26", - "@finos/vuu-datagrid": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15", + "@salt-ds/core": "1.13.2", "@salt-ds/theme": "1.7.1", - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2", "react-router-dom": "^6.2.1" }, "devDependencies": { @@ -12360,12 +13200,12 @@ } }, "@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "requires": { - "@babel/highlight": "^7.22.10", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "dependencies": { @@ -12413,31 +13253,31 @@ } }, "@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true }, "@babel/core": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", - "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", + "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-compilation-targets": "^7.22.10", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.10", - "@babel/parser": "^7.22.10", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.6", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "dependencies": { @@ -12450,26 +13290,26 @@ } }, "@babel/generator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", - "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "requires": { - "@babel/types": "^7.22.10", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" } }, "@babel/helper-compilation-targets": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", - "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -12483,19 +13323,19 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true }, "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { @@ -12508,25 +13348,25 @@ } }, "@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" } }, "@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" } }, "@babel/helper-plugin-utils": { @@ -12554,41 +13394,41 @@ } }, "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true }, "@babel/helpers": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", - "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", + "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6" } }, "@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, @@ -12637,24 +13477,24 @@ } }, "@babel/parser": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", - "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz", - "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5" } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz", - "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5" @@ -12679,42 +13519,42 @@ } }, "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", - "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", + "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.10", - "@babel/types": "^7.22.10", - "debug": "^4.1.0", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", - "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -12803,9 +13643,9 @@ "requires": {} }, "@cypress/request": { - "version": "2.88.12", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.12.tgz", - "integrity": "sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -12821,7 +13661,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "~6.10.3", + "qs": "6.10.4", "safe-buffer": "^5.1.2", "tough-cookie": "^4.1.3", "tunnel-agent": "^0.6.0", @@ -12854,157 +13694,164 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, + "@esbuild/aix-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz", + "integrity": "sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==", + "dev": true, + "optional": true + }, "@esbuild/android-arm": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", - "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", + "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", - "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", + "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", - "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", + "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", - "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", + "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", - "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", + "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", - "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", + "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", - "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", + "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", - "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", + "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", - "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", + "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", - "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", + "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", - "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", + "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", - "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", + "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", - "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", + "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", - "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", + "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", - "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", + "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", - "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", + "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", - "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", + "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", - "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", + "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", - "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", + "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", - "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", + "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", - "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", + "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", - "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", + "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", "dev": true, "optional": true }, @@ -13068,20 +13915,17 @@ "@faker-js/faker": "^8.0.2", "@finos/vuu-data-ag-grid": "0.0.26", "@finos/vuu-data-test": "0.0.26", - "@finos/vuu-datagrid": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@mdx-js/esbuild": "^2.3.0", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15", + "@salt-ds/core": "1.13.2", "@salt-ds/theme": "1.7.1", "@thomaschaplin/isin-generator": "^1.0.3", - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2", "react-router-dom": "^6.2.1" } }, @@ -13120,6 +13964,16 @@ "@finos/vuu-utils": "0.0.26" } }, + "@finos/vuu-data-local": { + "version": "file:packages/vuu-data-local", + "requires": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", + "@finos/vuu-utils": "0.0.26" + } + }, "@finos/vuu-data-react": { "version": "file:packages/vuu-data-react", "requires": { @@ -13133,11 +13987,23 @@ "@finos/vuu-utils": "0.0.26" } }, + "@finos/vuu-data-remote": { + "version": "file:packages/vuu-data-remote", + "requires": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-filter-parser": "0.0.26", + "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", + "@finos/vuu-utils": "0.0.26" + } + }, "@finos/vuu-data-test": { "version": "file:packages/vuu-data-test", "requires": { "@finos/vuu-data": "0.0.26", - "@finos/vuu-table-types": "0.0.26" + "@finos/vuu-table-types": "0.0.26", + "@thomaschaplin/isin-generator": "1.0.3" } }, "@finos/vuu-data-types": { @@ -13147,14 +14013,6 @@ "@finos/vuu-protocol-types": "0.0.26" } }, - "@finos/vuu-datagrid": { - "version": "file:packages/vuu-datagrid", - "requires": { - "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26", - "@finos/vuu-table-types": "0.0.26" - } - }, "@finos/vuu-datatable": { "version": "file:packages/vuu-datatable", "requires": { @@ -13194,8 +14052,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/lab": "1.0.0-alpha.15", + "@salt-ds/core": "1.13.2", "@types/uuid": "^9.0.2", "uuid": "9.0.0" }, @@ -13211,27 +14068,24 @@ "@finos/vuu-layout": { "version": "file:packages/vuu-layout", "requires": { + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0" + "@salt-ds/core": "1.13.2" } }, "@finos/vuu-popups": { "version": "file:packages/vuu-popups", "requires": { - "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", - "@finos/vuu-shell": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2" } }, "@finos/vuu-protocol-types": { @@ -13248,33 +14102,29 @@ "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2", + "html-to-image": "^1.11.11" } }, "@finos/vuu-table": { "version": "file:packages/vuu-table", "requires": { - "@finos/vuu-data": "0.0.26", - "@finos/vuu-data-react": "0.0.26", "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", - "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2" } }, "@finos/vuu-table-extras": { "version": "file:packages/vuu-table-extras", "requires": { "@finos/vuu-codemirror": "0.0.26", - "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", @@ -13283,8 +14133,7 @@ "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", "@lezer/lr": "1.3.4", - "@salt-ds/core": "1.8.0", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2" }, "dependencies": { "@lezer/lr": { @@ -13307,19 +14156,19 @@ "@finos/vuu-ui-controls": { "version": "file:packages/vuu-ui-controls", "requires": { - "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0" + "@salt-ds/core": "1.13.2" } }, "@finos/vuu-utils": { "version": "file:packages/vuu-utils", "requires": { + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-protocol-types": "0.0.26", "@finos/vuu-table-types": "0.0.26" @@ -13606,9 +14455,9 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", @@ -13710,49 +14559,124 @@ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.2.tgz", "integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==" }, + "@rollup/rollup-android-arm-eabi": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz", + "integrity": "sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==", + "dev": true, + "optional": true + }, + "@rollup/rollup-android-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz", + "integrity": "sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz", + "integrity": "sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz", + "integrity": "sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz", + "integrity": "sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz", + "integrity": "sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz", + "integrity": "sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz", + "integrity": "sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz", + "integrity": "sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz", + "integrity": "sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz", + "integrity": "sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz", + "integrity": "sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz", + "integrity": "sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==", + "dev": true, + "optional": true + }, "@salt-ds/core": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@salt-ds/core/-/core-1.8.0.tgz", - "integrity": "sha512-Na8/PEQdb93i6UvYeIn6PhLqjF3k7EbAI+/4zkHO/XeqCBGkRxK3EMibEPkw4Zwfw5PQZbDKgPxknW53aWP0AA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@salt-ds/core/-/core-1.13.2.tgz", + "integrity": "sha512-dBw4QErYpNgfj0wL2kKeZtdoiRXS6ZFgXHSh37yBHrP/QIqFNmhwCAWGR84OgNgetU6FhKvKSSgknwyHAK0fcg==", "requires": { "@floating-ui/react": "^0.23.0", - "@salt-ds/icons": "^1.6.0", - "@salt-ds/styles": "^0.1.1", + "@salt-ds/icons": "^1.9.0", + "@salt-ds/styles": "^0.2.0", "@salt-ds/window": "^0.1.1", "clsx": "^2.0.0" }, "dependencies": { "@salt-ds/icons": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@salt-ds/icons/-/icons-1.6.0.tgz", - "integrity": "sha512-/9c1L5LyU5cPxaYDyywDu8VnpvOvnaDmuLr/BWLEdyzxSzXTDfcIPtSgpaSaPadubvnnE9mhXdNknLyTqjNXZg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@salt-ds/icons/-/icons-1.9.0.tgz", + "integrity": "sha512-82PnI/9KStt/owSTV/+vxH5AkJaYDEKuJrBbzeC2axxipv8ydbToTaCn6usLOSTm9CQ04rzMFPNcWQSpGUHtjA==", "requires": { - "@salt-ds/styles": "^0.1.1", + "@salt-ds/styles": "^0.2.0", "@salt-ds/window": "^0.1.1", "clsx": "^2.0.0" } }, - "clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" - } - } - }, - "@salt-ds/icons": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@salt-ds/icons/-/icons-1.5.1.tgz", - "integrity": "sha512-yBWRk3hcmYKrPTPQTvJsg4K3TBIvtoznaVIeYj8Gg6zy14s4gUN9N4PH9xix0pNgyCFGgluHUTiUKG6AcyGVkA==", - "requires": { - "@salt-ds/styles": "^0.1.1", - "@salt-ds/window": "^0.1.1", - "clsx": "^2.0.0" - }, - "dependencies": { - "clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" + "@salt-ds/styles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@salt-ds/styles/-/styles-0.2.0.tgz", + "integrity": "sha512-tPd/XK1PFkPkBsYwh4fhDbo997eaev6row9aaz/sPM0FpEpU8nbvQRhxtr8iA/S4Q5hCj0xrk/jGTuK40V13oQ==", + "requires": {} } } }, @@ -13790,11 +14714,6 @@ "@salt-ds/window": "^0.1.1", "clsx": "^2.0.0" } - }, - "clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" } } }, @@ -13830,19 +14749,19 @@ } }, "@testing-library/cypress": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-9.0.0.tgz", - "integrity": "sha512-c1XiCGeHGGTWn0LAU12sFUfoX3qfId5gcSE2yHode+vsyHDWraxDPALjVnHd4/Fa3j4KBcc5k++Ccy6A9qnkMA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-10.0.1.tgz", + "integrity": "sha512-e8uswjTZIBhaIXjzEcrQQ8nHRWHgZH7XBxKuIWxZ/T7FxfWhCR48nFhUX5nfPizjVOKSThEfOSv67jquc1ASkw==", "dev": true, "requires": { "@babel/runtime": "^7.14.6", - "@testing-library/dom": "^8.1.0" + "@testing-library/dom": "^9.0.0" } }, "@testing-library/dom": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", - "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", + "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", @@ -13903,14 +14822,12 @@ "@thomaschaplin/cusip-generator": { "version": "1.0.22", "resolved": "https://registry.npmjs.org/@thomaschaplin/cusip-generator/-/cusip-generator-1.0.22.tgz", - "integrity": "sha512-162DBgkPGQI0otk/aW8z7XjyYM1fEOUf+p4yiEgJZhKupSWuwSNcsIcAi4fDZvP/XkI/pBF83aXUlYkWFMqA2Q==", - "dev": true + "integrity": "sha512-162DBgkPGQI0otk/aW8z7XjyYM1fEOUf+p4yiEgJZhKupSWuwSNcsIcAi4fDZvP/XkI/pBF83aXUlYkWFMqA2Q==" }, "@thomaschaplin/isin-generator": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@thomaschaplin/isin-generator/-/isin-generator-1.0.3.tgz", "integrity": "sha512-M1vm7MsTdLhOybs21dR1M0/aUAwpM2B7qZvcVMTzxBxnjzwaqCr1EtxMUjecCOoxViIA6A/HO7emlfKUGODBNQ==", - "dev": true, "requires": { "@thomaschaplin/cusip-generator": "^1.0.1" } @@ -13933,24 +14850,50 @@ } }, "@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true }, - "@types/chai": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", - "dev": true + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", "dev": true, "requires": { - "@types/chai": "*" + "@babel/types": "^7.20.7" } }, "@types/cypress": { @@ -14105,9 +15048,12 @@ "dev": true }, "@types/node": { - "version": "14.18.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz", - "integrity": "sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==" + "version": "18.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", + "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "requires": { + "undici-types": "~5.26.4" + } }, "@types/normalize-package-data": { "version": "2.4.1", @@ -14162,9 +15108,9 @@ "dev": true }, "@types/testing-library__cypress": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@types/testing-library__cypress/-/testing-library__cypress-5.0.9.tgz", - "integrity": "sha512-WTiIZhZKWDnV+Tgo42pxff8YfHdmaNFQz/bFoTlmfw2vbXcstCcb39VRaRi5yFHj/lb7t3K47btKYEbR1fci+Q==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@types/testing-library__cypress/-/testing-library__cypress-5.0.13.tgz", + "integrity": "sha512-lkxNGVFBEX825Z/FrHA8FLuKv1q5L6Bccqm08Zds2MUG4gd5al32hCpplzVumke3br+hkhtVmuPTfwQadIkc5w==", "dev": true, "requires": { "@testing-library/dom": "^7.11.0", @@ -14396,43 +15342,44 @@ } }, "@vitejs/plugin-react": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz", - "integrity": "sha512-7wU921ABnNYkETiMaZy7XqpueMnpu5VxvVps13MjmCo+utBdD79sZzrApHawHtVX66cCJQQTXFcjH0y9dSUK8g==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", "dev": true, "requires": { - "@babel/core": "^7.22.9", - "@babel/plugin-transform-react-jsx-self": "^7.22.5", - "@babel/plugin-transform-react-jsx-source": "^7.22.5", + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.0" } }, "@vitest/expect": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", - "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.1.0.tgz", + "integrity": "sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w==", "dev": true, "requires": { - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", "chai": "^4.3.10" } }, "@vitest/runner": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", - "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.1.0.tgz", + "integrity": "sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw==", "dev": true, "requires": { - "@vitest/utils": "0.34.6", - "p-limit": "^4.0.0", + "@vitest/utils": "1.1.0", + "p-limit": "^5.0.0", "pathe": "^1.1.1" }, "dependencies": { "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dev": true, "requires": { "yocto-queue": "^1.0.0" @@ -14447,14 +15394,14 @@ } }, "@vitest/snapshot": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", - "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.1.0.tgz", + "integrity": "sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ==", "dev": true, "requires": { - "magic-string": "^0.30.1", + "magic-string": "^0.30.5", "pathe": "^1.1.1", - "pretty-format": "^29.5.0" + "pretty-format": "^29.7.0" }, "dependencies": { "pretty-format": { @@ -14477,23 +15424,23 @@ } }, "@vitest/spy": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", - "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.1.0.tgz", + "integrity": "sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg==", "dev": true, "requires": { - "tinyspy": "^2.1.1" + "tinyspy": "^2.2.0" } }, "@vitest/utils": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", - "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.1.0.tgz", + "integrity": "sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ==", "dev": true, "requires": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" }, "dependencies": { "diff-sequences": { @@ -14521,6 +15468,12 @@ } } }, + "@zeit/schemas": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.29.0.tgz", + "integrity": "sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA==", + "dev": true + }, "abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -14529,6 +15482,16 @@ "optional": true, "peer": true }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, "acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -14541,9 +15504,9 @@ "requires": {} }, "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true }, "agent-base": { @@ -14578,6 +15541,15 @@ "uri-js": "^4.2.2" } }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, "ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -14615,11 +15587,11 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", "@fontsource/open-sans": "^4.5.13", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15", - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } }, "arch": { @@ -14628,6 +15600,12 @@ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -14854,6 +15832,85 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "boxen": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", + "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", + "dev": true, + "requires": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.0", + "chalk": "^5.0.1", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -14872,15 +15929,15 @@ } }, "browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" } }, "buffer": { @@ -14899,6 +15956,21 @@ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true }, + "bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "requires": { + "run-applescript": "^7.0.0" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true + }, "cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -14912,13 +15984,14 @@ "dev": true }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" } }, "callsites": { @@ -14953,9 +16026,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001519", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz", - "integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "dev": true }, "caseless": { @@ -14991,6 +16064,60 @@ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true }, + "chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "requires": { + "chalk": "^4.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -15036,17 +16163,18 @@ "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true }, - "classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" - }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, + "cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "dev": true + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -15081,6 +16209,48 @@ "resolved": "https://registry.npmjs.org/clipboard-copy/-/clipboard-copy-4.0.1.tgz", "integrity": "sha512-wOlqdqziE/NNTUJsfSgXmBMIrYmfd5V0HCGsR8uAKHcg+h9NENWINcfRjtWGU77wDHC8B8ijV4hMTGYbrKovng==" }, + "clipboardy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "dev": true, + "requires": { + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" + }, + "dependencies": { + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + } + } + }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -15093,9 +16263,9 @@ } }, "clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" }, "color-convert": { "version": "1.9.3", @@ -15151,6 +16321,53 @@ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "compute-scroll-into-view": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", @@ -15161,10 +16378,16 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "dev": true + }, "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, "core-js-pure": { @@ -15246,14 +16469,14 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "cypress": { - "version": "12.17.3", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.3.tgz", - "integrity": "sha512-/R4+xdIDjUSLYkiQfwJd630S81KIgicmQOLXotFxVXkl+eTeVO+3bHXxdi5KBh/OgC33HWN33kHX+0tQR/ZWpg==", + "version": "13.6.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.1.tgz", + "integrity": "sha512-k1Wl5PQcA/4UoTffYKKaxA0FJKwg8yenYNYRzLt11CUR0Kln+h7Udne6mdU1cUIdXBDTVZWtmiUjzqGs7/pEpw==", "dev": true, "requires": { - "@cypress/request": "^2.88.11", + "@cypress/request": "^3.0.0", "@cypress/xvfb": "^1.2.4", - "@types/node": "^16.18.39", + "@types/node": "^18.17.5", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", @@ -15286,6 +16509,7 @@ "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", + "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", "semver": "^7.5.3", @@ -15295,12 +16519,6 @@ "yauzl": "^2.10.0" }, "dependencies": { - "@types/node": { - "version": "16.18.40", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.40.tgz", - "integrity": "sha512-+yno3ItTEwGxXiS/75Q/aHaa5srkpnJaH+kdkTVJ3DtJEwv92itpKbxU+FjPoh2m/5G9zmUQfrL4A4C13c+iGA==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -15349,9 +16567,9 @@ } }, "cypress-axe": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cypress-axe/-/cypress-axe-1.4.0.tgz", - "integrity": "sha512-Ut7NKfzjyKm0BEbt2WxuKtLkIXmx6FD2j0RwdvO/Ykl7GmB/qRQkwbKLk3VP35+83hiIr8GKD04PDdrTK5BnyA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cypress-axe/-/cypress-axe-1.5.0.tgz", + "integrity": "sha512-Hy/owCjfj+25KMsecvDgo4fC/781ccL+e8p+UUYoadGVM2ogZF9XIKbiM6KI8Y3cEaSreymdD6ZzccbI2bY0lQ==", "dev": true, "requires": {} }, @@ -15363,21 +16581,11 @@ "requires": {} }, "cypress-real-events": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/cypress-real-events/-/cypress-real-events-1.10.0.tgz", - "integrity": "sha512-ALSdCiG+Rj3Sl6qooqTFeFGBxOIe8QJUcgIuJ6ZVBanTEijXRzqxqstMC2ZKfixqj1TyNjolyZU4zOoN/jtHpg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/cypress-real-events/-/cypress-real-events-1.11.0.tgz", + "integrity": "sha512-4LXVRsyq+xBh5TmlEyO1ojtBXtN7xw720Pwb9rEE9rkJuXmeH3VyoR1GGayMGr+Itqf11eEjfDewtDmcx6PWPQ==", "dev": true, - "requires": { - "prettier": "^3.0.0" - }, - "dependencies": { - "prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz", - "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==", - "dev": true - } - } + "requires": {} }, "dashdash": { "version": "1.14.1", @@ -15478,15 +16686,15 @@ } }, "deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "dev": true, "requires": { "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", @@ -15496,13 +16704,19 @@ "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", + "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.13" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -15513,10 +16727,37 @@ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" }, + "default-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.0.tgz", + "integrity": "sha512-EviRCeDkniKC30N3uKNHIaIsBZEo00ZOrxDZQmJwJeY2q6Uli5SwfmQ6wSf5aezcBS3PDHoQJl/XuAHEfMCJFg==", + "dev": true, + "requires": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + } + }, + "default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true + }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true }, "define-properties": { @@ -15585,6 +16826,12 @@ "webidl-conversions": "^7.0.0" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -15596,9 +16843,9 @@ } }, "electron-to-chromium": { - "version": "1.4.490", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz", - "integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==", + "version": "1.4.615", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", + "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==", "dev": true }, "emoji-regex": { @@ -15737,43 +16984,64 @@ } }, "esbuild": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", - "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.17.18", - "@esbuild/android-arm64": "0.17.18", - "@esbuild/android-x64": "0.17.18", - "@esbuild/darwin-arm64": "0.17.18", - "@esbuild/darwin-x64": "0.17.18", - "@esbuild/freebsd-arm64": "0.17.18", - "@esbuild/freebsd-x64": "0.17.18", - "@esbuild/linux-arm": "0.17.18", - "@esbuild/linux-arm64": "0.17.18", - "@esbuild/linux-ia32": "0.17.18", - "@esbuild/linux-loong64": "0.17.18", - "@esbuild/linux-mips64el": "0.17.18", - "@esbuild/linux-ppc64": "0.17.18", - "@esbuild/linux-riscv64": "0.17.18", - "@esbuild/linux-s390x": "0.17.18", - "@esbuild/linux-x64": "0.17.18", - "@esbuild/netbsd-x64": "0.17.18", - "@esbuild/openbsd-x64": "0.17.18", - "@esbuild/sunos-x64": "0.17.18", - "@esbuild/win32-arm64": "0.17.18", - "@esbuild/win32-ia32": "0.17.18", - "@esbuild/win32-x64": "0.17.18" + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", + "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.19.10", + "@esbuild/android-arm": "0.19.10", + "@esbuild/android-arm64": "0.19.10", + "@esbuild/android-x64": "0.19.10", + "@esbuild/darwin-arm64": "0.19.10", + "@esbuild/darwin-x64": "0.19.10", + "@esbuild/freebsd-arm64": "0.19.10", + "@esbuild/freebsd-x64": "0.19.10", + "@esbuild/linux-arm": "0.19.10", + "@esbuild/linux-arm64": "0.19.10", + "@esbuild/linux-ia32": "0.19.10", + "@esbuild/linux-loong64": "0.19.10", + "@esbuild/linux-mips64el": "0.19.10", + "@esbuild/linux-ppc64": "0.19.10", + "@esbuild/linux-riscv64": "0.19.10", + "@esbuild/linux-s390x": "0.19.10", + "@esbuild/linux-x64": "0.19.10", + "@esbuild/netbsd-x64": "0.19.10", + "@esbuild/openbsd-x64": "0.19.10", + "@esbuild/sunos-x64": "0.19.10", + "@esbuild/win32-arm64": "0.19.10", + "@esbuild/win32-ia32": "0.19.10", + "@esbuild/win32-x64": "0.19.10" } }, "esbuild-visualizer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/esbuild-visualizer/-/esbuild-visualizer-0.4.1.tgz", - "integrity": "sha512-5XI3unzqPr3xqfzR/mzK3LhoAJs3FQhiIXBsKJ3Oh6CjyjuXz6HVmhJMoisrcpeTZip65fR54Dk53MZncA0AUQ==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/esbuild-visualizer/-/esbuild-visualizer-0.5.1.tgz", + "integrity": "sha512-itlh5S2/QqKandylO3C+jANKM/EgNSJNOuT6L14zLWTqsewEPSxlgGunQ5tTWRhlsjON+4S2FZ96a66ItGICnw==", "dev": true, "requires": { "open": "^8.4.0", + "picomatch": "^2.3.1", "yargs": "^17.6.2" + }, + "dependencies": { + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true + }, + "open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + } } }, "escalade": { @@ -16199,6 +17467,23 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dev": true, + "requires": { + "punycode": "^1.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + } + } + }, "fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -16227,6 +17512,7 @@ "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -16238,7 +17524,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" } }, @@ -16258,7 +17544,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" } }, @@ -16278,7 +17564,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" } }, @@ -16298,7 +17584,7 @@ "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" } }, @@ -16421,16 +17707,16 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, "function.prototype.name": { @@ -16470,15 +17756,15 @@ "dev": true }, "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-stream": { @@ -16721,6 +18007,15 @@ "has-symbols": "^1.0.2" } }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, "hast-util-to-estree": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", @@ -17061,6 +18356,23 @@ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "dev": true }, + "is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "requires": { + "is-docker": "^3.0.0" + }, + "dependencies": { + "is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true + } + } + }, "is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -17114,6 +18426,12 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true }, + "is-port-reachable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", + "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", + "dev": true + }, "is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -17527,10 +18845,14 @@ } }, "local-pkg": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", - "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", - "dev": true + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "requires": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + } }, "locate-path": { "version": "6.0.0", @@ -18382,9 +19704,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true }, "natural-compare": { @@ -18398,6 +19720,12 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, "no-scroll": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/no-scroll/-/no-scroll-2.1.1.tgz", @@ -18421,9 +19749,9 @@ } }, "node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "normalize-package-data": { @@ -18543,6 +19871,12 @@ "es-abstract": "^1.20.4" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -18561,14 +19895,26 @@ } }, "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.0.0.tgz", + "integrity": "sha512-WDekhGCZ7VHBw6sNDzCl42rVL315m/K/A1lYiZO2nHXn9T4yPBXxvrZKYkVPtsCahD815yhFNR9/Wq608PdIaA==", "dev": true, "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "default-browser": "^5.2.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "requires": { + "is-inside-container": "^1.0.0" + } + } } }, "optionator": { @@ -18670,6 +20016,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -18681,6 +20033,12 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -18750,12 +20108,12 @@ } }, "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "dev": true, "requires": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -18826,6 +20184,12 @@ "react-is": "^17.0.1" } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, "prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -18902,6 +20266,38 @@ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "dev": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + } + } + }, "react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -19019,12 +20415,6 @@ } } }, - "recoil": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.1.3.tgz", - "integrity": "sha512-/Rm7wN7jqCjhtFK1TgtK0V115SUXNu6d4QYvwxWNLydib0QChSmpB6U8CaHoRPS0MFWtAIsD/IFjpbfk/OYm7Q==", - "requires": {} - }, "redent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", @@ -19049,14 +20439,33 @@ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "set-function-name": "^2.0.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "dev": true, + "requires": { + "rc": "^1.0.1" } }, "remark-mdx": { @@ -19171,11 +20580,24 @@ } }, "rollup": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", - "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", - "dev": true, - "requires": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz", + "integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==", + "dev": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.9.1", + "@rollup/rollup-android-arm64": "4.9.1", + "@rollup/rollup-darwin-arm64": "4.9.1", + "@rollup/rollup-darwin-x64": "4.9.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.1", + "@rollup/rollup-linux-arm64-gnu": "4.9.1", + "@rollup/rollup-linux-arm64-musl": "4.9.1", + "@rollup/rollup-linux-riscv64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-musl": "4.9.1", + "@rollup/rollup-win32-arm64-msvc": "4.9.1", + "@rollup/rollup-win32-ia32-msvc": "4.9.1", + "@rollup/rollup-win32-x64-msvc": "4.9.1", "fsevents": "~2.3.2" } }, @@ -19195,6 +20617,12 @@ "@babel/runtime": "^7.1.2" } }, + "run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -19299,6 +20727,107 @@ } } }, + "serve": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.1.tgz", + "integrity": "sha512-48er5fzHh7GCShLnNyPBRPEjs2I6QBozeGr02gaacROiyS/8ARADlj595j39iZXAqBbJHH/ivJJyPRWY9sQWZA==", + "dev": true, + "requires": { + "@zeit/schemas": "2.29.0", + "ajv": "8.11.0", + "arg": "5.0.2", + "boxen": "7.0.0", + "chalk": "5.0.1", + "chalk-template": "0.4.0", + "clipboardy": "3.0.0", + "compression": "1.7.4", + "is-port-reachable": "4.0.0", + "serve-handler": "6.1.5", + "update-check": "1.5.4" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + } + } + }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -19428,9 +20957,9 @@ "dev": true }, "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -19450,10 +20979,20 @@ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, + "standalone-table": { + "version": "file:sample-apps/standalone-table", + "requires": { + "@finos/vuu-table": "0.0.26", + "@fontsource/open-sans": "^4.5.13", + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" + } + }, "std-env": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz", - "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.6.0.tgz", + "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", "dev": true }, "stop-iteration-iterator": { @@ -19800,9 +21339,9 @@ "dev": true }, "tinybench": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", - "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", + "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", "dev": true }, "tinycolor2": { @@ -19811,9 +21350,9 @@ "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" }, "tinypool": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", - "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.1.tgz", + "integrity": "sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==", "dev": true }, "tinyspy": { @@ -20009,9 +21548,9 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" }, "ufo": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz", - "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", "dev": true }, "unbox-primitive": { @@ -20026,6 +21565,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "unified": { "version": "10.1.2", "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", @@ -20127,15 +21671,25 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" } }, + "update-check": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", + "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", + "dev": true, + "requires": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -20188,6 +21742,12 @@ "spdx-expression-parse": "^3.0.0" } }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -20222,221 +21782,34 @@ } }, "vite": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", - "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", + "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", "dev": true, "requires": { - "esbuild": "^0.18.10", - "fsevents": "~2.3.2", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "dependencies": { - "@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "dev": true, - "optional": true - }, - "esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - } + "esbuild": "^0.19.3", + "fsevents": "~2.3.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" } }, "vite-node": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", - "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.1.0.tgz", + "integrity": "sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q==", "dev": true, "requires": { "cac": "^6.7.14", "debug": "^4.3.4", - "mlly": "^1.4.0", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "vite": "^5.0.0" } }, "vite-tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.2.tgz", + "integrity": "sha512-dq0FjyxHHDnp0uS3P12WEOX2W7NeuLzX9AWP38D7Zw2CTbFErapwQVlCiT5DMJcVWKQ1MMdTe92PZl/rBQ7qcw==", "dev": true, "requires": { "debug": "^4.1.1", @@ -20445,35 +21818,111 @@ } }, "vitest": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", - "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.1.0.tgz", + "integrity": "sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A==", "dev": true, "requires": { - "@types/chai": "^4.3.5", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "@vitest/expect": "0.34.6", - "@vitest/runner": "0.34.6", - "@vitest/snapshot": "0.34.6", - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", - "acorn": "^8.9.0", - "acorn-walk": "^8.2.0", + "@vitest/expect": "1.1.0", + "@vitest/runner": "1.1.0", + "@vitest/snapshot": "1.1.0", + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", + "acorn-walk": "^8.3.0", "cac": "^6.7.14", "chai": "^4.3.10", "debug": "^4.3.4", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.1", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "strip-literal": "^1.0.1", - "tinybench": "^2.5.0", - "tinypool": "^0.7.0", - "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", - "vite-node": "0.34.6", + "std-env": "^3.5.0", + "strip-literal": "^1.3.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.1", + "vite": "^5.0.0", + "vite-node": "1.1.0", "why-is-node-running": "^2.2.2" + }, + "dependencies": { + "execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + } + }, + "get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true + }, + "human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } } }, "w3c-keyname": { @@ -20565,13 +22014,13 @@ } }, "which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, "requires": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.4", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" @@ -20587,6 +22036,49 @@ "stackback": "0.0.2" } }, + "widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dev": true, + "requires": { + "string-width": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/vuu-ui/package.json b/vuu-ui/package.json index 6511b5ef5..badd87b1d 100644 --- a/vuu-ui/package.json +++ b/vuu-ui/package.json @@ -14,15 +14,18 @@ "showcase" ], "scripts": { - "lint": "eslint . --ext .js,.jsx", + "lint": "eslint . --ext .js,.jsx,.ts,.tsx", + "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix", "prettier": "prettier './**/*.{js,,mjs,jsx,css,md,json}' --config ./.prettierrc", "format": "prettier --write './**/*.{js,,mjs,jsx,css,md,json}' --config ./.prettierrc", "build": "node ./scripts/build-all.mjs", "build:app": "cd sample-apps/app-vuu-example && node scripts/build.mjs", + "build:table": "cd sample-apps/standalone-table && node scripts/build.mjs", "build:packages": "npm run build -- --cjs --license && npm run type-defs", "build:packages:debug": "npm run build -- --cjs --debug && npm run type-defs -- --debug", "build:salt": "node ./scripts/build-salt.mjs", "launch:demo": "node ./scripts/launch-app.mjs", + "launch:table": "node ./scripts/launch-table.mjs", "launch:demo:electron": "cd tools/electron && node ./node_modules/.bin/electron .", "launch:showcase": " cd showcase && node scripts/launch.mjs", "deploy:websocket-test": "node ./tools/deploy-websocket-test.mjs", @@ -41,34 +44,33 @@ "typecheck": "tsc --noEmit --project tsconfig-typecheck.json" }, "dependencies": { + "@salt-ds/core": "1.13.2", "@types/jest": "^26.0.20", - "@types/node": "^14.14.35", + "@types/node": "^18.0.0", "@types/react": "^17.0.2", "@types/react-dom": "^17.0.2", "@typescript-eslint/parser": "^5.41.0", - "classnames": "^2.3.1", - "clsx": "^1.2.1", + "clsx": "^2.0.0", "html-to-image": "^1.11.11", "react": "^17.0.2", "react-dom": "^17.0.2", - "recoil": "^0.1.3", "semver": "^7.5.2" }, "devDependencies": { "@heswell/component-anatomy": "0.0.5", "@lezer/generator": "^1.2.2", - "@testing-library/cypress": "^9.0.0", + "@testing-library/cypress": "10.0.1", "@types/jsdom": "^21.1.2", - "@types/testing-library__cypress": "^5.0.9", + "@types/testing-library__cypress": "5.0.13", "@typescript-eslint/eslint-plugin": "^5.41.0", - "@vitejs/plugin-react": "^4.0.2", + "@vitejs/plugin-react": "4.2.1", "chalk": "^5.2.0", - "cypress": "^12.3.0", - "cypress-axe": "^1.2.0", - "cypress-iframe": "^1.0.1", - "cypress-real-events": "^1.7.6", - "esbuild": "0.17.18", - "esbuild-visualizer": "^0.4.0", + "cypress": "13.6.1", + "cypress-axe": "1.5.0", + "cypress-iframe": "1.0.1", + "cypress-real-events": "1.11.0", + "esbuild": "0.19.10", + "esbuild-visualizer": "0.5.1", "eslint": "8.36.0", "eslint-config-prettier": "8.7.0", "eslint-plugin-cypress": "^2.13.3", @@ -76,14 +78,15 @@ "eslint-plugin-react": "7.32.2", "eslint-plugin-react-hooks": "4.6.0", "happy-dom": "^10.10.0", - "open": "^8.4.0", + "open": "10.0.0", "prettier": "2.8.4", + "serve": "^14.2.1", "stylelint": "^15.0.0", "tinycolor2": "1.4.2", "typescript": "4.9.5", - "vite": "4.5.0", - "vite-tsconfig-paths": "^4.0.3", - "vitest": "0.34.6" + "vite": "5.0.10", + "vite-tsconfig-paths": "4.2.2", + "vitest": "1.1.0" }, "engines": { "node": ">=16.0.0" diff --git a/vuu-ui/packages/vuu-data-ag-grid/package.json b/vuu-ui/packages/vuu-data-ag-grid/package.json index f179ce0a4..aa1d35dfa 100644 --- a/vuu-ui/packages/vuu-data-ag-grid/package.json +++ b/vuu-ui/packages/vuu-data-ag-grid/package.json @@ -18,6 +18,6 @@ "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "react": "^17.0.2" + "react": ">=17.0.2" } } diff --git a/vuu-ui/packages/vuu-data-ag-grid/src/ViewportRowModelDataSource.ts b/vuu-ui/packages/vuu-data-ag-grid/src/ViewportRowModelDataSource.ts index 3bb7f2c4a..decca8b38 100644 --- a/vuu-ui/packages/vuu-data-ag-grid/src/ViewportRowModelDataSource.ts +++ b/vuu-ui/packages/vuu-data-ag-grid/src/ViewportRowModelDataSource.ts @@ -1,16 +1,17 @@ import { DataSource, DataSourceConfig, - isVuuFeatureAction, SubscribeCallback, VuuFeatureMessage, -} from "@finos/vuu-data"; +} from "@finos/vuu-data-types"; +import {} from "@finos/vuu-data-remote"; import { Filter } from "@finos/vuu-filter-types"; import { VuuGroupBy, VuuSort } from "@finos/vuu-protocol-types"; import { buildColumnMap, ColumnMap, itemsOrOrderChanged, + isVuuFeatureAction, metadataKeys, } from "@finos/vuu-utils"; import { AgDataWindow } from "./AgDataWindow"; diff --git a/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts b/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts index 36fd4f937..b9a121599 100644 --- a/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts +++ b/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts @@ -1,15 +1,3 @@ -import { - DataSourceConfig, - isViewportMenusAction, - isVisualLinksAction, - MenuRpcResponse, - RemoteDataSource, - RpcResponseHandler, - VuuFeatureMessage, - VuuUIMessageInRPCEditReject, - VuuUIMessageInRPCEditResponse, -} from "@finos/vuu-data"; - import { MenuActionConfig, SuggestionFetcher, @@ -18,10 +6,17 @@ import { VuuMenuActionHandler, VuuServerMenuOptions, } from "@finos/vuu-data-react"; +import { VuuDataSource } from "@finos/vuu-data-remote"; -import { ColumnDescriptor } from "@finos/vuu-table-types"; +import { RpcResponseHandler, VuuFeatureMessage } from "@finos/vuu-data-types"; import { VuuGroupBy, VuuMenu, VuuTable } from "@finos/vuu-protocol-types"; -import { buildColumnMap, itemsOrOrderChanged } from "@finos/vuu-utils"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; +import { + buildColumnMap, + isViewportMenusAction, + isVisualLinksAction, + itemsOrOrderChanged, +} from "@finos/vuu-utils"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { AgData } from "./AgDataWindow"; import { @@ -91,7 +86,7 @@ export const agSortChangedEventToVuuSortDef = (evt: AgSortChangedEvent) => { export interface ViewportRowModelHookProps { columns?: ColumnDescriptor[]; - dataSource: RemoteDataSource; + dataSource: VuuDataSource; onFeatureEnabled?: (message: VuuFeatureMessage) => void; onRpcResponse?: RpcResponseHandler; vuuMenuActionHandler?: VuuMenuActionHandler; @@ -101,9 +96,8 @@ type GroupByConfigChange = { groupBy: VuuGroupBy; }; -const hasGroupByChange = ( - message?: Partial -): message is GroupByConfigChange => Array.isArray(message?.groupBy); +const hasGroupByChange = (message?: unknown): message is GroupByConfigChange => + Array.isArray((message as GroupByConfigChange).groupBy); export const useViewportRowModel = ({ columns, diff --git a/vuu-ui/packages/vuu-data-local/package.json b/vuu-ui/packages/vuu-data-local/package.json new file mode 100644 index 000000000..9bf3e826d --- /dev/null +++ b/vuu-ui/packages/vuu-data-local/package.json @@ -0,0 +1,21 @@ +{ + "name": "@finos/vuu-data-local", + "version": "0.0.26", + "main": "src/index.ts", + "author": "heswell", + "license": "Apache-2.0", + "scripts": { + "build": "node ../../scripts/run-build.mjs", + "test": "vitest run", + "type-defs": "node ../../scripts/build-type-defs.mjs" + }, + "devDependencies": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", + "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26" + }, + "dependencies": { + "@finos/vuu-utils": "0.0.26" + } +} diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/aggregate-utils.ts b/vuu-ui/packages/vuu-data-local/src/array-data-source/aggregate-utils.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/array-data-source/aggregate-utils.ts rename to vuu-ui/packages/vuu-data-local/src/array-data-source/aggregate-utils.ts diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts b/vuu-ui/packages/vuu-data-local/src/array-data-source/array-data-source.ts similarity index 97% rename from vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts rename to vuu-ui/packages/vuu-data-local/src/array-data-source/array-data-source.ts index 32db5b321..cc46c6747 100644 --- a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts +++ b/vuu-ui/packages/vuu-data-local/src/array-data-source/array-data-source.ts @@ -1,5 +1,20 @@ -import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; -import { ColumnDescriptor, Selection } from "@finos/vuu-table-types"; +import { + DataSource, + DataSourceConfig, + DataSourceConstructorProps, + DataSourceEvents, + DataSourceFilter, + DataSourceRow, + DataSourceStatus, + MenuRpcResponse, + Selection, + SubscribeCallback, + SubscribeProps, + TableSchema, + VuuUIMessageInRPCEditReject, + VuuUIMessageInRPCEditResponse, + WithFullConfig, +} from "@finos/vuu-data-types"; import { filterPredicate, parseFilter } from "@finos/vuu-filter-parser"; import { ClientToServerEditRpc, @@ -12,12 +27,18 @@ import { VuuRowDataItemType, VuuSort, } from "@finos/vuu-protocol-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { buildColumnMap, ColumnMap, + configChanged, EventEmitter, getAddedItems, getMissingItems, + groupByChanged, + hasFilter, + hasGroupBy, + hasSort, KeySet, logger, metadataKeys, @@ -25,34 +46,13 @@ import { rangeNewItems, resetRange, uuid, -} from "@finos/vuu-utils"; -import { - configChanged, - DataSource, - DataSourceConfig, - DataSourceConstructorProps, - DataSourceEvents, - DataSourceStatus, - groupByChanged, - hasFilter, - hasGroupBy, - hasSort, - SubscribeCallback, - SubscribeProps, vanillaConfig, withConfigDefaults, - WithFullConfig, -} from "../data-source"; -import { TableSchema } from "../message-utils"; -import { - MenuRpcResponse, - VuuUIMessageInRPCEditReject, - VuuUIMessageInRPCEditResponse, -} from "../vuuUIMessageTypes"; +} from "@finos/vuu-utils"; import { aggregateData } from "./aggregate-utils"; +import { buildDataToClientMap, toClientRow } from "./array-data-utils"; import { collapseGroup, expandGroup, GroupMap, groupRows } from "./group-utils"; import { sortRows } from "./sort-utils"; -import { buildDataToClientMap, toClientRow } from "./array-data-utils"; const { KEY } = metadataKeys; @@ -243,22 +243,22 @@ export class ArrayDataSource } suspend() { - console.log("noop"); + // console.log("noop"); return this; } resume() { - console.log("resume noop"); + // console.log("resume noop"); return this; } disable() { - console.log("disable noop"); + // console.log("disable noop"); return this; } enable() { - console.log("enable noop"); + // console.log("enable noop"); return this; } diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts b/vuu-ui/packages/vuu-data-local/src/array-data-source/array-data-utils.ts similarity index 94% rename from vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts rename to vuu-ui/packages/vuu-data-local/src/array-data-source/array-data-utils.ts index f38c81ff1..894b785b4 100644 --- a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts +++ b/vuu-ui/packages/vuu-data-local/src/array-data-source/array-data-utils.ts @@ -1,5 +1,4 @@ -import { DataSourceRow } from "@finos/vuu-data-types"; -import { Selection } from "@finos/vuu-table-types"; +import { DataSourceRow, Selection } from "@finos/vuu-data-types"; import { ColumnMap, getSelectionStatus, diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts b/vuu-ui/packages/vuu-data-local/src/array-data-source/group-utils.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts rename to vuu-ui/packages/vuu-data-local/src/array-data-source/group-utils.ts diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/sort-utils.ts b/vuu-ui/packages/vuu-data-local/src/array-data-source/sort-utils.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/array-data-source/sort-utils.ts rename to vuu-ui/packages/vuu-data-local/src/array-data-source/sort-utils.ts diff --git a/vuu-ui/packages/vuu-data-local/src/index.ts b/vuu-ui/packages/vuu-data-local/src/index.ts new file mode 100644 index 000000000..59509f61a --- /dev/null +++ b/vuu-ui/packages/vuu-data-local/src/index.ts @@ -0,0 +1,2 @@ +export * from "./array-data-source/array-data-source"; +export * from "./json-data-source/json-data-source"; diff --git a/vuu-ui/packages/vuu-data/src/json-data-source.ts b/vuu-ui/packages/vuu-data-local/src/json-data-source/json-data-source.ts similarity index 97% rename from vuu-ui/packages/vuu-data/src/json-data-source.ts rename to vuu-ui/packages/vuu-data-local/src/json-data-source/json-data-source.ts index 2ecd2d5c2..52ae71db8 100644 --- a/vuu-ui/packages/vuu-data/src/json-data-source.ts +++ b/vuu-ui/packages/vuu-data-local/src/json-data-source/json-data-source.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor, Selection } from "@finos/vuu-table-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { LinkDescriptorWithLabel, VuuGroupBy, @@ -9,17 +9,9 @@ import { ClientToServerEditRpc, VuuRowDataItemType, } from "@finos/vuu-protocol-types"; -import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; import { - EventEmitter, - isSelected, - JsonData, - jsonToDataSourceRows, - KeySet, - metadataKeys, - uuid, -} from "@finos/vuu-utils"; -import type { + DataSourceFilter, + DataSourceRow, DataSource, DataSourceConstructorProps, DataSourceEvents, @@ -27,13 +19,21 @@ import type { SubscribeCallback, SubscribeProps, WithFullConfig, -} from "./data-source"; -import { vanillaConfig } from "./data-source"; -import { + Selection, MenuRpcResponse, VuuUIMessageInRPCEditReject, VuuUIMessageInRPCEditResponse, -} from "./vuuUIMessageTypes"; +} from "@finos/vuu-data-types"; +import { + EventEmitter, + isSelected, + JsonData, + jsonToDataSourceRows, + KeySet, + metadataKeys, + uuid, + vanillaConfig, +} from "@finos/vuu-utils"; const NULL_SCHEMA = { columns: [], key: "", table: { module: "", table: "" } }; diff --git a/vuu-ui/packages/vuu-data/tsconfig.json b/vuu-ui/packages/vuu-data-local/tsconfig.json similarity index 100% rename from vuu-ui/packages/vuu-data/tsconfig.json rename to vuu-ui/packages/vuu-data-local/tsconfig.json diff --git a/vuu-ui/packages/vuu-data-react/package.json b/vuu-ui/packages/vuu-data-react/package.json index 048d88a6c..9056d8b20 100644 --- a/vuu-ui/packages/vuu-data-react/package.json +++ b/vuu-ui/packages/vuu-data-react/package.json @@ -22,6 +22,6 @@ "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "react": "^17.0.2" + "react": ">=17.0.2" } } diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useDataSource.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useDataSource.ts index bba3b6fb9..80a067a81 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useDataSource.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useDataSource.ts @@ -1,6 +1,9 @@ // TODO is this hook needed ? it is currently used only in a vuu salt story -import { DataSource, SubscribeCallback } from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; +import { + DataSource, + DataSourceRow, + SubscribeCallback, +} from "@finos/vuu-data-types"; import { VuuRange } from "@finos/vuu-protocol-types"; import { getFullRange, metadataKeys, WindowRange } from "@finos/vuu-utils"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts index 750535edc..863e9d2b3 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts @@ -3,7 +3,7 @@ import { ListOption, LookupTableDetails, } from "@finos/vuu-table-types"; -import { RemoteDataSource } from "@finos/vuu-data"; +import { VuuDataSource } from "@finos/vuu-data-remote"; import { useShellContext } from "@finos/vuu-shell"; import { buildColumnMap, @@ -29,7 +29,7 @@ const loadLookupValues = ({ const promise: Promise = new Promise((resolve) => { const columns = [valueColumn, labelColumn]; const columnMap = buildColumnMap(columns); - const dataSource = new RemoteDataSource({ + const dataSource = new VuuDataSource({ bufferSize: 0, table, }); diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionQuality.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionQuality.ts index e6b985910..052a9926e 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionQuality.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionQuality.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useState } from "react"; -import { ConnectionManager } from "@finos/vuu-data"; +import { ConnectionManager } from "@finos/vuu-data-remote"; export const useServerConnectionQuality = () => { const [messagesPerSecond, setMessagesPerSecond] = useState(0); diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionStatus.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionStatus.ts index 7654d9393..6f80c0862 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionStatus.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useServerConnectionStatus.ts @@ -1,5 +1,6 @@ import { useCallback, useEffect, useState } from "react"; -import { ConnectionManager, ConnectionStatusMessage } from "@finos/vuu-data"; +import { ConnectionManager } from "@finos/vuu-data-remote"; +import { ConnectionStatusMessage } from "@finos/vuu-data-types"; export const useServerConnectionStatus = () => { const [connectionStatus, setConnectionStatus] = useState("disconnected"); diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useTypeaheadSuggestions.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useTypeaheadSuggestions.ts index 69fa72802..1d673ca79 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useTypeaheadSuggestions.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useTypeaheadSuggestions.ts @@ -5,7 +5,7 @@ import { VuuTable, } from "@finos/vuu-protocol-types"; import { useCallback } from "react"; -import { makeRpcCall } from "@finos/vuu-data"; +import { makeRpcCall } from "@finos/vuu-data-remote"; export type SuggestionFetcher = (params: TypeaheadParams) => Promise; diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts index 1c23861f1..3dfbc4c21 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts @@ -1,18 +1,17 @@ import { + ContextMenuItemDescriptor, DataSource, + DataSourceRow, DataSourceVisualLinkCreatedMessage, + MenuActionHandler, + MenuBuilder, MenuRpcResponse, ViewportRpcResponse, VuuUIMessageInRPCEditReject, VuuUIMessageInRPCEditResponse, -} from "@finos/vuu-data"; -import { - ContextMenuItemDescriptor, - DataSourceRow, - MenuActionHandler, - MenuBuilder, } from "@finos/vuu-data-types"; import { getFilterPredicate } from "@finos/vuu-filter-parser"; +import type { MenuActionClosePopup } from "@finos/vuu-popups"; import { ClientToServerMenuCellRPC, ClientToServerMenuRowRPC, @@ -29,7 +28,6 @@ import { isGroupMenuItemDescriptor, metadataKeys, } from "@finos/vuu-utils"; -import type { MenuActionClosePopup } from "@finos/vuu-popups"; import { useCallback } from "react"; export const addRowsFromInstruments = "addRowsFromInstruments"; diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuTables.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuTables.ts index fa8f4c33f..b987e660a 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuTables.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuTables.ts @@ -1,6 +1,7 @@ -import { getServerAPI, TableSchema } from "@finos/vuu-data"; +import { getServerAPI } from "@finos/vuu-data-remote"; +import { TableSchema } from "@finos/vuu-data-types"; import { VuuTable } from "@finos/vuu-protocol-types"; -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; export const useVuuTables = () => { const [tables, setTables] = useState | undefined>(); diff --git a/vuu-ui/packages/vuu-data/README.md b/vuu-ui/packages/vuu-data-remote/README.md similarity index 100% rename from vuu-ui/packages/vuu-data/README.md rename to vuu-ui/packages/vuu-data-remote/README.md diff --git a/vuu-ui/packages/vuu-data/package.json b/vuu-ui/packages/vuu-data-remote/package.json similarity index 93% rename from vuu-ui/packages/vuu-data/package.json rename to vuu-ui/packages/vuu-data-remote/package.json index cea774552..7eadb0376 100644 --- a/vuu-ui/packages/vuu-data/package.json +++ b/vuu-ui/packages/vuu-data-remote/package.json @@ -1,5 +1,5 @@ { - "name": "@finos/vuu-data", + "name": "@finos/vuu-data-remote", "version": "0.0.26", "main": "src/index.ts", "author": "heswell", diff --git a/vuu-ui/packages/vuu-data/src/authenticate.ts b/vuu-ui/packages/vuu-data-remote/src/authenticate.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/authenticate.ts rename to vuu-ui/packages/vuu-data-remote/src/authenticate.ts diff --git a/vuu-ui/packages/vuu-data/src/connection-manager.ts b/vuu-ui/packages/vuu-data-remote/src/connection-manager.ts similarity index 97% rename from vuu-ui/packages/vuu-data/src/connection-manager.ts rename to vuu-ui/packages/vuu-data-remote/src/connection-manager.ts index 5448196c8..be52a03ff 100644 --- a/vuu-ui/packages/vuu-data/src/connection-manager.ts +++ b/vuu-ui/packages/vuu-data-remote/src/connection-manager.ts @@ -1,3 +1,15 @@ +import { + ConnectionStatusMessage, + DataSourceCallbackMessage, + ServerProxySubscribeMessage, + TableSchema, + VuuUIMessageIn, + VuuUIMessageInRPC, + VuuUIMessageInTableList, + VuuUIMessageInTableMeta, + VuuUIMessageOut, + WebSocketProtocol, +} from "@finos/vuu-data-types"; import { ClientToServerMenuRPC, ClientToServerTableList, @@ -10,32 +22,18 @@ import { import { EventEmitter, getLoggingConfigForWorker, - uuid, -} from "@finos/vuu-utils"; -import { - DataSourceCallbackMessage, - shouldMessageBeRoutedToDataSource as messageShouldBeRoutedToDataSource, -} from "./data-source"; -import * as Message from "./server-proxy/messages"; -import { - ConnectionStatusMessage, isConnectionQualityMetrics, isConnectionStatusMessage, isTableSchema, messageHasResult, - ServerProxySubscribeMessage, - VuuUIMessageIn, - VuuUIMessageInRPC, - VuuUIMessageInTableList, - VuuUIMessageInTableMeta, - VuuUIMessageOut, -} from "./vuuUIMessageTypes"; + uuid, +} from "@finos/vuu-utils"; +import { shouldMessageBeRoutedToDataSource as messageShouldBeRoutedToDataSource } from "./data-source"; +import * as Message from "./server-proxy/messages"; // Note: inlined-worker is a generated file, it must be built +import { ConnectionQualityMetrics } from "@finos/vuu-data-types"; import { workerSourceCode } from "./inlined-worker"; -import { ConnectionQualityMetrics } from "./vuuUIMessageTypes"; -import { WebSocketProtocol } from "./websocket-connection"; -import { TableSchema } from "./message-utils"; const workerBlob = new Blob([getLoggingConfigForWorker() + workerSourceCode], { type: "text/javascript", diff --git a/vuu-ui/packages/vuu-data/src/connectionTypes.ts b/vuu-ui/packages/vuu-data-remote/src/connectionTypes.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/connectionTypes.ts rename to vuu-ui/packages/vuu-data-remote/src/connectionTypes.ts diff --git a/vuu-ui/packages/vuu-data/src/constants.ts b/vuu-ui/packages/vuu-data-remote/src/constants.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/constants.ts rename to vuu-ui/packages/vuu-data-remote/src/constants.ts diff --git a/vuu-ui/packages/vuu-data-remote/src/data-source.ts b/vuu-ui/packages/vuu-data-remote/src/data-source.ts new file mode 100644 index 000000000..246b3846f --- /dev/null +++ b/vuu-ui/packages/vuu-data-remote/src/data-source.ts @@ -0,0 +1,86 @@ +import { + DataSourceCallbackMessage, + DataSourceConfig, + DataSourceConfigMessage, + DataSourceDataSizeMessage, +} from "@finos/vuu-data-types"; +import { + ServerToClientBody, + ServerToClientMenuSessionTableAction, + VuuTable, +} from "@finos/vuu-protocol-types"; + +export const isSizeOnly = ( + message: DataSourceCallbackMessage +): message is DataSourceDataSizeMessage => + message.type === "viewport-update" && message.mode === "size-only"; + +export const toDataSourceConfig = ( + message: DataSourceConfigMessage +): DataSourceConfig => { + switch (message.type) { + case "aggregate": + return { aggregations: message.aggregations }; + case "columns": + return { columns: message.columns }; + case "filter": + return { filter: message.filter }; + case "groupBy": + return { groupBy: message.groupBy }; + case "sort": + return { sort: message.sort }; + case "config": + return message.config; + } +}; + +const datasourceMessages = [ + "config", + "aggregate", + "viewport-update", + "columns", + "debounce-begin", + "disabled", + "enabled", + "filter", + "groupBy", + "vuu-link-created", + "vuu-link-removed", + "vuu-links", + "vuu-menu", + "sort", + "subscribed", +]; + +export const shouldMessageBeRoutedToDataSource = ( + message: unknown +): message is DataSourceCallbackMessage => { + const type = (message as DataSourceCallbackMessage).type; + return datasourceMessages.includes(type); +}; + +export const isDataSourceConfigMessage = ( + message: DataSourceCallbackMessage +): message is DataSourceConfigMessage => + ["config", "aggregate", "columns", "filter", "groupBy", "sort"].includes( + message.type + ); + +export const isSessionTableActionMessage = ( + messageBody: ServerToClientBody +): messageBody is ServerToClientMenuSessionTableAction => + messageBody.type === "VIEW_PORT_MENU_RESP" && + messageBody.action !== null && + isSessionTable(messageBody.action.table); + +export const isSessionTable = (table?: unknown) => { + if ( + table !== null && + typeof table === "object" && + "table" in table && + "module" in table + ) { + return (table as VuuTable).table.startsWith("session"); + } + return false; +}; diff --git a/vuu-ui/packages/vuu-data/src/index.ts b/vuu-ui/packages/vuu-data-remote/src/index.ts similarity index 56% rename from vuu-ui/packages/vuu-data/src/index.ts rename to vuu-ui/packages/vuu-data-remote/src/index.ts index cdd32b612..ee1570327 100644 --- a/vuu-ui/packages/vuu-data/src/index.ts +++ b/vuu-ui/packages/vuu-data-remote/src/index.ts @@ -4,7 +4,4 @@ export type { ServerAPI } from "./connection-manager"; export * from "./constants"; export * from "./data-source"; export * from "./message-utils"; -export * from "./array-data-source/array-data-source"; -export * from "./json-data-source"; -export * from "./remote-data-source"; -export * from "./vuuUIMessageTypes"; +export * from "./vuu-data-source"; diff --git a/vuu-ui/packages/vuu-data-remote/src/inlined-worker.js b/vuu-ui/packages/vuu-data-remote/src/inlined-worker.js new file mode 100644 index 000000000..5c8428f16 --- /dev/null +++ b/vuu-ui/packages/vuu-data-remote/src/inlined-worker.js @@ -0,0 +1,8 @@ +export const workerSourceCode = ` +var ie=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var m=(r,e,t)=>(ie(r,e,"read from private field"),t?t.call(r):e.get(r)),ae=(r,e,t)=>{if(e.has(r))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(r):e.set(r,t)},ue=(r,e,t,s)=>(ie(r,e,"write to private field"),s?s.call(r,t):e.set(r,t),t);function le(r,e,t=[],s=[]){for(let n=0,o=r.length;n{var e,t;if(((e=globalThis.document)==null?void 0:e.cookie)!==void 0)return(t=globalThis.document.cookie.split("; ").find(s=>s.startsWith(\`\${r}=\`)))==null?void 0:t.split("=")[1]};function G({from:r,to:e},t=0,s=Number.MAX_SAFE_INTEGER){if(t===0)return sr>=e&&r=this.to||tr.type==="connection-status",de=r=>r.type==="connection-metrics";var ge=r=>"viewport"in r;var Qe=["error","warn","info","debug"],Ye=r=>typeof r=="string"&&Qe.includes(r),Ze="error",P=()=>{},Xe="error",{loggingLevel:L=Xe}=et(),b=r=>{let e=L==="debug",t=e||L==="info",s=t||L==="warn",n=s||L==="error",o=t?p=>console.info(\`[\${r}] \${p}\`):P,i=s?p=>console.warn(\`[\${r}] \${p}\`):P,u=e?p=>console.debug(\`[\${r}] \${p}\`):P;return{errorEnabled:n,error:n?p=>console.error(\`[\${r}] \${p}\`):P}};function et(){return typeof loggingSettings<"u"?loggingSettings:{loggingLevel:tt()}}function tt(){let r=ce("vuu-logging-level");return Ye(r)?r:Ze}var{debug:st,debugEnabled:nt}=b("range-monitor"),k=class{constructor(e){this.source=e;this.range={from:0,to:0};this.timestamp=0}isSet(){return this.timestamp!==0}set({from:e,to:t}){let{timestamp:s}=this;if(this.range.from=e,this.range.to=t,this.timestamp=performance.now(),s)nt&&st(\`<\${this.source}> [\${e}-\${t}], \${(this.timestamp-s).toFixed(0)} ms elapsed\`);else return 0}};var O=class{constructor(e){this.keys=new Map,this.free=[],this.nextKeyValue=0,this.reset(e)}next(){return this.free.length>0?this.free.pop():this.nextKeyValue++}reset({from:e,to:t}){this.keys.forEach((n,o)=>{(o=t)&&(this.free.push(n),this.keys.delete(o))});let s=t-e;this.keys.size+this.free.length>s&&(this.free.length=Math.max(0,s-this.keys.size));for(let n=e;nthis.keys.size&&(this.nextKeyValue=this.keys.size)}keyFor(e){let t=this.keys.get(e);if(t===void 0)throw console.log(\`key not found + keys: \${this.toDebugString()} + free : \${this.free.join(",")} + \`),Error(\`KeySet, no key found for rowIndex \${e}\`);return t}toDebugString(){return Array.from(this.keys.entries()).map((e,t)=>\`\${e}=>\${t}\`).join(",")}};var{SELECTED:\$t}=\$,w={False:0,True:1,First:2,Last:4};var rt=(r,e)=>e>=r[0]&&e<=r[1],ot=w.True+w.First+w.Last,it=w.True+w.First,at=w.True+w.Last,z=(r,e)=>{for(let t of r)if(typeof t=="number"){if(t===e)return ot}else if(rt(t,e))return e===t[0]?it:e===t[1]?at:w.True;return w.False};var he=r=>{if(r.every(t=>typeof t=="number"))return r;let e=[];for(let t of r)if(typeof t=="number")e.push(t);else for(let s=t[0];s<=t[1];s++)e.push(s);return e};var fe=r=>r.type==="VIEW_PORT_MENU_RESP"&&r.action!==null&&x(r.action.table),x=r=>r!==null&&typeof r=="object"&&"table"in r&&"module"in r?r.table.startsWith("session"):!1;var ut=["VIEW_PORT_MENUS_SELECT_RPC","VIEW_PORT_MENU_TABLE_RPC","VIEW_PORT_MENU_ROW_RPC","VIEW_PORT_MENU_CELL_RPC","VP_EDIT_CELL_RPC","VP_EDIT_ROW_RPC","VP_EDIT_ADD_ROW_RPC","VP_EDIT_DELETE_CELL_RPC","VP_EDIT_DELETE_ROW_RPC","VP_EDIT_SUBMIT_FORM_RPC"],me=r=>ut.includes(r.type),Ce=r=>r.type==="VIEW_PORT_RPC_CALL",A=({requestId:r,...e})=>[r,e],Re=r=>{let e=r.at(0);if(e.updateType==="SIZE"){if(r.length===1)return r;e=r.at(1)}let t=r.at(-1);return[e,t]},Se=r=>{let e={};for(let t of r)(e[t.viewPortId]||(e[t.viewPortId]=[])).push(t);return e};var H=({columns:r,dataTypes:e,key:t,table:s})=>({table:s,columns:r.map((n,o)=>({name:n,serverDataType:e[o]})),key:t});var Te="CHANGE_VP_SUCCESS";var be="CLOSE_TREE_NODE",Ee="CLOSE_TREE_SUCCESS";var we="CREATE_VP",Ve="DISABLE_VP",ve="DISABLE_VP_SUCCESS";var ye="ENABLE_VP",Me="ENABLE_VP_SUCCESS";var K="GET_VP_VISUAL_LINKS",_e="GET_VIEW_PORT_MENUS";var Ie="HB",De="HB_RESP",Pe="LOGIN",Le="OPEN_TREE_NODE",ke="OPEN_TREE_SUCCESS";var Oe="REMOVE_VP";var xe="SET_SELECTION_SUCCESS";var Ne=r=>{switch(r){case"TypeAheadRpcHandler":return"TYPEAHEAD";default:return"SIMUL"}};var Ue=[],R=b("array-backed-moving-window");function lt(r,e){if(!e||e.data.length!==r.data.length||e.sel!==r.sel)return!1;for(let t=0;t{var t;if((t=R.info)==null||t.call(R,\`setRowCount \${e}\`),e{let s=this.bufferSize*.25;return m(this,h).to-t0&&e-m(this,h).from0&&this.clientRange.from+this.rowsWithinRange===this.rowCount}outOfRange(e,t){let{from:s,to:n}=this.range;if(t=n)return!0}setAtIndex(e){let{rowIndex:t}=e,s=t-m(this,h).from;if(lt(e,this.internalData[s]))return!1;let n=this.isWithinClientRange(t);return(n||this.isWithinRange(t))&&(!this.internalData[s]&&n&&(this.rowsWithinRange+=1),this.internalData[s]=e),n}getAtIndex(e){return m(this,h).isWithin(e)&&this.internalData[e-m(this,h).from]!=null?this.internalData[e-m(this,h).from]:void 0}isWithinRange(e){return m(this,h).isWithin(e)}isWithinClientRange(e){return this.clientRange.isWithin(e)}setClientRange(e,t){var p;(p=R.debug)==null||p.call(R,\`setClientRange \${e} - \${t}\`);let s=this.clientRange.from,n=Math.min(this.clientRange.to,this.rowCount);if(e===s&&t===n)return[!1,Ue];let o=this.clientRange.copy();this.clientRange.from=e,this.clientRange.to=t,this.rowsWithinRange=0;for(let a=e;ao.to){let a=Math.max(e,o.to);i=this.internalData.slice(a-u,t-u)}else{let a=Math.min(o.from,t);i=this.internalData.slice(e-u,a-u)}return[this.bufferBreakout(e,t),i]}setRange(e,t){var s,n;if(e!==m(this,h).from||t!==m(this,h).to){(s=R.debug)==null||s.call(R,\`setRange \${e} - \${t}\`);let[o,i]=m(this,h).overlap(e,t),u=new Array(t-e);this.rowsWithinRange=0;for(let c=o;c=0;o--)if(e[o]!==void 0){n=e[o];break}return s&&n?[s.rowIndex,n.rowIndex]:[-1,-1]}};h=new WeakMap;var ct=[],{debug:f,debugEnabled:U,error:pt,info:d,infoEnabled:dt,warn:y}=b("viewport"),gt=({rowKey:r,updateType:e})=>e==="U"&&!r.startsWith("\$root"),W=[void 0,void 0],ht={count:0,mode:void 0,size:0,ts:0},q=class{constructor({aggregations:e,bufferSize:t=50,columns:s,filter:n,groupBy:o=[],table:i,range:u,sort:c,title:p,viewport:a,visualLink:l},g){this.batchMode=!0;this.hasUpdates=!1;this.pendingUpdates=[];this.pendingOperations=new Map;this.pendingRangeRequests=[];this.rowCountChanged=!1;this.selectedRows=[];this.useBatchMode=!0;this.lastUpdateStatus=ht;this.updateThrottleTimer=void 0;this.rangeMonitor=new k("ViewPort");this.disabled=!1;this.isTree=!1;this.status="";this.suspended=!1;this.suspendTimer=null;this.setLastSizeOnlyUpdateSize=e=>{this.lastUpdateStatus.size=e};this.setLastUpdate=e=>{let{ts:t,mode:s}=this.lastUpdateStatus,n=0;if(s===e){let o=Date.now();this.lastUpdateStatus.count+=1,this.lastUpdateStatus.ts=o,n=t===0?0:o-t}else this.lastUpdateStatus.count=1,this.lastUpdateStatus.ts=0,n=0;return this.lastUpdateStatus.mode=e,n};this.rangeRequestAlreadyPending=e=>{let{bufferSize:t}=this,s=t*.25,{from:n}=e;for(let{from:o,to:i}of this.pendingRangeRequests)if(n>=o&&n{this.updateThrottleTimer=void 0,this.lastUpdateStatus.count=3,this.postMessageToClient({clientViewportId:this.clientViewportId,mode:"size-only",size:this.lastUpdateStatus.size,type:"viewport-update"})};this.shouldThrottleMessage=e=>{let t=this.setLastUpdate(e);return e==="size-only"&&t>0&&t<500&&this.lastUpdateStatus.count>3};this.throttleMessage=e=>this.shouldThrottleMessage(e)?(d==null||d("throttling updates setTimeout to 2000"),this.updateThrottleTimer===void 0&&(this.updateThrottleTimer=setTimeout(this.sendThrottledSizeMessage,2e3)),!0):(this.updateThrottleTimer!==void 0&&(clearTimeout(this.updateThrottleTimer),this.updateThrottleTimer=void 0),!1);this.getNewRowCount=()=>{if(this.rowCountChanged&&this.dataWindow)return this.rowCountChanged=!1,this.dataWindow.rowCount};this.aggregations=e,this.bufferSize=t,this.clientRange=u,this.clientViewportId=a,this.columns=s,this.filter=n,this.groupBy=o,this.keys=new O(u),this.pendingLinkedParent=l,this.table=i,this.sort=c,this.title=p,dt&&(d==null||d(\`constructor #\${a} \${i.table} bufferSize=\${t}\`)),this.dataWindow=new N(this.clientRange,u,this.bufferSize),this.postMessageToClient=g}get hasUpdatesToProcess(){return this.suspended?!1:this.rowCountChanged||this.hasUpdates}get size(){var e;return(e=this.dataWindow.rowCount)!=null?e:0}subscribe(){let{filter:e}=this.filter;return this.status=this.status==="subscribed"?"resubscribing":"subscribing",{type:we,table:this.table,range:G(this.clientRange,this.bufferSize),aggregations:this.aggregations,columns:this.columns,sort:this.sort,groupBy:this.groupBy,filterSpec:{filter:e}}}handleSubscribed({viewPortId:e,aggregations:t,columns:s,filterSpec:n,range:o,sort:i,groupBy:u},c){return this.serverViewportId=e,this.status="subscribed",this.aggregations=t,this.columns=s,this.groupBy=u,this.isTree=u&&u.length>0,this.dataWindow.setRange(o.from,o.to),{aggregations:t,type:"subscribed",clientViewportId:this.clientViewportId,columns:s,filter:n,groupBy:u,range:o,sort:i,tableSchema:c}}awaitOperation(e,t){this.pendingOperations.set(e,t)}completeOperation(e,...t){var u;let{clientViewportId:s,pendingOperations:n}=this,o=n.get(e);if(!o){pt(\`no matching operation found to complete for requestId \${e}\`);return}let{type:i}=o;if(d==null||d(\`completeOperation \${i}\`),n.delete(e),i==="CHANGE_VP_RANGE"){let[c,p]=t;(u=this.dataWindow)==null||u.setRange(c,p);for(let a=this.pendingRangeRequests.length-1;a>=0;a--){let l=this.pendingRangeRequests[a];if(l.requestId===e){l.acked=!0;break}else y==null||y("range requests sent faster than they are being ACKed")}}else if(i==="config"){let{aggregations:c,columns:p,filter:a,groupBy:l,sort:g}=o.data;return this.aggregations=c,this.columns=p,this.filter=a,this.groupBy=l,this.sort=g,l.length>0?this.isTree=!0:this.isTree&&(this.isTree=!1),f==null||f(\`config change confirmed, isTree : \${this.isTree}\`),{clientViewportId:s,type:i,config:o.data}}else{if(i==="groupBy")return this.isTree=o.data.length>0,this.groupBy=o.data,f==null||f(\`groupBy change confirmed, isTree : \${this.isTree}\`),{clientViewportId:s,type:i,groupBy:o.data};if(i==="columns")return this.columns=o.data,{clientViewportId:s,type:i,columns:o.data};if(i==="filter")return this.filter=o.data,{clientViewportId:s,type:i,filter:o.data};if(i==="aggregate")return this.aggregations=o.data,{clientViewportId:s,type:"aggregate",aggregations:this.aggregations};if(i==="sort")return this.sort=o.data,{clientViewportId:s,type:i,sort:this.sort};if(i!=="selection"){if(i==="disable")return this.disabled=!0,{type:"disabled",clientViewportId:s};if(i==="enable")return this.disabled=!1,{type:"enabled",clientViewportId:s};if(i==="CREATE_VISUAL_LINK"){let[c,p,a]=t;return this.linkedParent={colName:c,parentViewportId:p,parentColName:a},this.pendingLinkedParent=void 0,{type:"vuu-link-created",clientViewportId:s,colName:c,parentViewportId:p,parentColName:a}}else if(i==="REMOVE_VISUAL_LINK")return this.linkedParent=void 0,{type:"vuu-link-removed",clientViewportId:s}}}}rangeRequest(e,t){U&&this.rangeMonitor.set(t);let s="CHANGE_VP_RANGE";if(this.dataWindow){let[n,o]=this.dataWindow.setClientRange(t.from,t.to),i,u=this.dataWindow.rowCount||void 0,c=n&&!this.rangeRequestAlreadyPending(t)?{type:s,viewPortId:this.serverViewportId,...G(t,this.bufferSize,u)}:null;if(c){U&&(f==null||f(\`create CHANGE_VP_RANGE: [\${c.from} - \${c.to}]\`)),this.awaitOperation(e,{type:s});let a=this.pendingRangeRequests.at(-1);if(a)if(a.acked)console.warn("Range Request before previous request is filled");else{let{from:l,to:g}=a;this.dataWindow.outOfRange(l,g)?i={clientViewportId:this.clientViewportId,type:"debounce-begin"}:y==null||y("Range Request before previous request is acked")}this.pendingRangeRequests.push({...c,requestId:e}),this.useBatchMode&&(this.batchMode=!0)}else o.length>0&&(this.batchMode=!1);this.keys.reset(this.dataWindow.clientRange);let p=this.isTree?j:J;return o.length?[c,o.map(a=>p(a,this.keys,this.selectedRows))]:i?[c,void 0,i]:[c]}else return[null]}setLinks(e){return this.links=e,[{type:"vuu-links",links:e,clientViewportId:this.clientViewportId},this.pendingLinkedParent]}setMenu(e){return{type:"vuu-menu",menu:e,clientViewportId:this.clientViewportId}}openTreeNode(e,t){return this.useBatchMode&&(this.batchMode=!0),{type:Le,vpId:this.serverViewportId,treeKey:t.key}}closeTreeNode(e,t){return this.useBatchMode&&(this.batchMode=!0),{type:be,vpId:this.serverViewportId,treeKey:t.key}}createLink(e,t,s,n){let o={type:"CREATE_VISUAL_LINK",parentVpId:s,childVpId:this.serverViewportId,parentColumnName:n,childColumnName:t};return this.awaitOperation(e,o),this.useBatchMode&&(this.batchMode=!0),o}removeLink(e){let t={type:"REMOVE_VISUAL_LINK",childVpId:this.serverViewportId};return this.awaitOperation(e,t),t}suspend(){this.suspended=!0,d==null||d("suspend")}resume(){return this.suspended=!1,U&&(f==null||f(\`resume: \${this.currentData()}\`)),[this.size,this.currentData()]}currentData(){let e=[];if(this.dataWindow){let t=this.dataWindow.getData(),{keys:s}=this,n=this.isTree?j:J;for(let o of t)o&&e.push(n(o,s,this.selectedRows))}return e}enable(e){return this.awaitOperation(e,{type:"enable"}),d==null||d(\`enable: \${this.serverViewportId}\`),{type:ye,viewPortId:this.serverViewportId}}disable(e){return this.awaitOperation(e,{type:"disable"}),d==null||d(\`disable: \${this.serverViewportId}\`),this.suspended=!1,{type:Ve,viewPortId:this.serverViewportId}}columnRequest(e,t){return this.awaitOperation(e,{type:"columns",data:t}),f==null||f(\`columnRequest: \${t}\`),this.createRequest({columns:t})}filterRequest(e,t){this.awaitOperation(e,{type:"filter",data:t}),this.useBatchMode&&(this.batchMode=!0);let{filter:s}=t;return d==null||d(\`filterRequest: \${s}\`),this.createRequest({filterSpec:{filter:s}})}setConfig(e,t){this.awaitOperation(e,{type:"config",data:t});let{filter:s,...n}=t;return this.useBatchMode&&(this.batchMode=!0),U?f==null||f(\`setConfig \${JSON.stringify(t)}\`):d==null||d("setConfig"),this.createRequest({...n,filterSpec:typeof(s==null?void 0:s.filter)=="string"?{filter:s.filter}:{filter:""}},!0)}aggregateRequest(e,t){return this.awaitOperation(e,{type:"aggregate",data:t}),d==null||d(\`aggregateRequest: \${t}\`),this.createRequest({aggregations:t})}sortRequest(e,t){return this.awaitOperation(e,{type:"sort",data:t}),d==null||d(\`sortRequest: \${JSON.stringify(t.sortDefs)}\`),this.createRequest({sort:t})}groupByRequest(e,t=ct){var s;return this.awaitOperation(e,{type:"groupBy",data:t}),this.useBatchMode&&(this.batchMode=!0),this.isTree||(s=this.dataWindow)==null||s.clear(),this.createRequest({groupBy:t})}selectRequest(e,t){return this.selectedRows=t,this.awaitOperation(e,{type:"selection",data:t}),d==null||d(\`selectRequest: \${t}\`),{type:"SET_SELECTION",vpId:this.serverViewportId,selection:he(t)}}removePendingRangeRequest(e,t){for(let s=this.pendingRangeRequests.length-1;s>=0;s--){let{from:n,to:o}=this.pendingRangeRequests[s],i=!0;if(e>=n&&en&&t0){e=[],t="update";for(let i of this.pendingUpdates)e.push(o(i,s,n));this.pendingUpdates.length=0}else{let i=this.dataWindow.getData();if(this.dataWindow.hasAllRowsWithinRange){e=[],t="batch";for(let u of i)e.push(o(u,s,n));this.batchMode=!1}}this.hasUpdates=!1}return this.throttleMessage(t)?W:[e,t]}createRequest(e,t=!1){return t?{type:"CHANGE_VP",viewPortId:this.serverViewportId,...e}:{type:"CHANGE_VP",viewPortId:this.serverViewportId,aggregations:this.aggregations,columns:this.columns,sort:this.sort,groupBy:this.groupBy,filterSpec:{filter:this.filter.filter},...e}}},J=({rowIndex:r,rowKey:e,sel:t,data:s},n,o)=>[r,n.keyFor(r),!0,!1,0,0,e,t?z(o,r):0].concat(s),j=({rowIndex:r,rowKey:e,sel:t,data:s},n,o)=>{let[i,u,,c,,p,...a]=s;return[r,n.keyFor(r),c,u,i,p,e,t?z(o,r):0].concat(a)};var We=1;var{debug:V,debugEnabled:Q,error:M,info:T,infoEnabled:ft,warn:Y}=b("server-proxy"),C=()=>\`\${We++}\`,mt={},Ct=r=>r.disabled!==!0&&r.suspended!==!0,Rt={type:"NO_ACTION"},St=(r,e,t)=>r.map(s=>s.parentVpId===e?{...s,label:t}:s);function Tt(r,e){return r.map(t=>{let{parentVpId:s}=t,n=e.get(s);if(n)return{...t,parentClientVpId:n.clientViewportId,label:n.title};throw Error("addLabelsToLinks viewport not found")})}var F=class{constructor(e,t){this.authToken="";this.user="user";this.pendingRequests=new Map;this.queuedRequests=[];this.cachedTableMetaRequests=new Map;this.cachedTableSchemas=new Map;this.connection=e,this.postMessageToClient=t,this.viewports=new Map,this.mapClientToServerViewport=new Map}async reconnect(){await this.login(this.authToken);let[e,t]=le(Array.from(this.viewports.values()),Ct);this.viewports.clear(),this.mapClientToServerViewport.clear();let s=n=>{n.forEach(o=>{let{clientViewportId:i}=o;this.viewports.set(i,o),this.sendMessageToServer(o.subscribe(),i)})};s(e),setTimeout(()=>{s(t)},2e3)}async login(e,t="user"){if(e)return this.authToken=e,this.user=t,new Promise((s,n)=>{this.sendMessageToServer({type:Pe,token:this.authToken,user:t},""),this.pendingLogin={resolve:s,reject:n}});this.authToken===""&&M("login, cannot login until auth token has been obtained")}subscribe(e){if(this.mapClientToServerViewport.has(e.viewport))M(\`spurious subscribe call \${e.viewport}\`);else{let t=this.getTableMeta(e.table),s=new q(e,this.postMessageToClient);this.viewports.set(e.viewport,s);let n=this.awaitResponseToMessage(s.subscribe(),e.viewport);Promise.all([n,t]).then(([i,u])=>{let{viewPortId:c}=i,{status:p}=s;e.viewport!==c&&(this.viewports.delete(e.viewport),this.viewports.set(c,s)),this.mapClientToServerViewport.set(e.viewport,c);let a=s.handleSubscribed(i,u);a&&(this.postMessageToClient(a),Q&&V(\`post DataSourceSubscribedMessage to client: \${JSON.stringify(a)}\`)),s.disabled&&this.disableViewport(s),this.queuedRequests.length>0&&this.processQueuedRequests(),p==="subscribing"&&!x(s.table)&&(this.sendMessageToServer({type:K,vpId:c}),this.sendMessageToServer({type:_e,vpId:c}),Array.from(this.viewports.entries()).filter(([l,{disabled:g}])=>l!==c&&!g).forEach(([l])=>{this.sendMessageToServer({type:K,vpId:l})}))})}}processQueuedRequests(){let e={};for(;this.queuedRequests.length;){let t=this.queuedRequests.pop();if(t){let{clientViewportId:s,message:n,requestId:o}=t;if(n.type==="CHANGE_VP_RANGE"){if(e.CHANGE_VP_RANGE)continue;e.CHANGE_VP_RANGE=!0;let i=this.mapClientToServerViewport.get(s);i&&this.sendMessageToServer({...n,viewPortId:i},o)}}}}unsubscribe(e){let t=this.mapClientToServerViewport.get(e);t?(T==null||T(\`Unsubscribe Message (Client to Server): + \${t}\`),this.sendMessageToServer({type:Oe,viewPortId:t})):M(\`failed to unsubscribe client viewport \${e}, viewport not found\`)}getViewportForClient(e,t=!0){let s=this.mapClientToServerViewport.get(e);if(s){let n=this.viewports.get(s);if(n)return n;if(t)throw Error(\`Viewport not found for client viewport \${e}\`);return null}else{if(this.viewports.has(e))return this.viewports.get(e);if(t)throw Error(\`Viewport server id not found for client viewport \${e}\`);return null}}setViewRange(e,t){let s=C(),[n,o,i]=e.rangeRequest(s,t.range);T==null||T(\`setViewRange \${t.range.from} - \${t.range.to}\`),n&&(this.sendIfReady(n,s,e.status==="subscribed")||this.queuedRequests.push({clientViewportId:t.viewport,message:n,requestId:s})),o?(T==null||T(\`setViewRange \${o.length} rows returned from cache\`),this.postMessageToClient({mode:"batch",type:"viewport-update",clientViewportId:e.clientViewportId,rows:o})):i&&this.postMessageToClient(i)}setConfig(e,t){let s=C(),n=e.setConfig(s,t.config);this.sendIfReady(n,s,e.status==="subscribed")}aggregate(e,t){let s=C(),n=e.aggregateRequest(s,t.aggregations);this.sendIfReady(n,s,e.status==="subscribed")}sort(e,t){let s=C(),n=e.sortRequest(s,t.sort);this.sendIfReady(n,s,e.status==="subscribed")}groupBy(e,t){let s=C(),n=e.groupByRequest(s,t.groupBy);this.sendIfReady(n,s,e.status==="subscribed")}filter(e,t){let s=C(),{filter:n}=t,o=e.filterRequest(s,n);this.sendIfReady(o,s,e.status==="subscribed")}setColumns(e,t){let s=C(),{columns:n}=t,o=e.columnRequest(s,n);this.sendIfReady(o,s,e.status==="subscribed")}setTitle(e,t){e&&(e.title=t.title,this.updateTitleOnVisualLinks(e))}select(e,t){let s=C(),{selected:n}=t,o=e.selectRequest(s,n);this.sendIfReady(o,s,e.status==="subscribed")}disableViewport(e){let t=C(),s=e.disable(t);this.sendIfReady(s,t,e.status==="subscribed")}enableViewport(e){if(e.disabled){let t=C(),s=e.enable(t);this.sendIfReady(s,t,e.status==="subscribed")}}suspendViewport(e){e.suspend(),e.suspendTimer=setTimeout(()=>{T==null||T("suspendTimer expired, escalate suspend to disable"),this.disableViewport(e)},3e3)}resumeViewport(e){e.suspendTimer&&(V==null||V("clear suspend timer"),clearTimeout(e.suspendTimer),e.suspendTimer=null);let[t,s]=e.resume();V==null||V(\`resumeViewport size \${t}, \${s.length} rows sent to client\`),this.postMessageToClient({clientViewportId:e.clientViewportId,mode:"batch",rows:s,size:t,type:"viewport-update"})}openTreeNode(e,t){if(e.serverViewportId){let s=C();this.sendIfReady(e.openTreeNode(s,t),s,e.status==="subscribed")}}closeTreeNode(e,t){if(e.serverViewportId){let s=C();this.sendIfReady(e.closeTreeNode(s,t),s,e.status==="subscribed")}}createLink(e,t){let{parentClientVpId:s,parentColumnName:n,childColumnName:o}=t,i=C(),u=this.mapClientToServerViewport.get(s);if(u){let c=e.createLink(i,o,u,n);this.sendMessageToServer(c,i)}else M("ServerProxy unable to create link, viewport not found")}removeLink(e){let t=C(),s=e.removeLink(t);this.sendMessageToServer(s,t)}updateTitleOnVisualLinks(e){var n;let{serverViewportId:t,title:s}=e;for(let o of this.viewports.values())if(o!==e&&o.links&&t&&s&&(n=o.links)!=null&&n.some(i=>i.parentVpId===t)){let[i]=o.setLinks(St(o.links,t,s));this.postMessageToClient(i)}}removeViewportFromVisualLinks(e){var t;for(let s of this.viewports.values())if((t=s.links)!=null&&t.some(({parentVpId:n})=>n===e)){let[n]=s.setLinks(s.links.filter(({parentVpId:o})=>o!==e));this.postMessageToClient(n)}}menuRpcCall(e){let t=this.getViewportForClient(e.vpId,!1);if(t!=null&&t.serverViewportId){let[s,n]=A(e);this.sendMessageToServer({...n,vpId:t.serverViewportId},s)}}viewportRpcCall(e){let t=this.getViewportForClient(e.vpId,!1);if(t!=null&&t.serverViewportId){let[s,n]=A(e);this.sendMessageToServer({...n,vpId:t.serverViewportId,namedParams:{}},s)}}rpcCall(e){let[t,s]=A(e),n=Ne(s.service);this.sendMessageToServer(s,t,{module:n})}handleMessageFromClient(e){var t;if(ge(e))if(e.type==="disable"){let s=this.getViewportForClient(e.viewport,!1);return s!==null?this.disableViewport(s):void 0}else{let s=this.getViewportForClient(e.viewport);switch(e.type){case"setViewRange":return this.setViewRange(s,e);case"config":return this.setConfig(s,e);case"aggregate":return this.aggregate(s,e);case"sort":return this.sort(s,e);case"groupBy":return this.groupBy(s,e);case"filter":return this.filter(s,e);case"select":return this.select(s,e);case"suspend":return this.suspendViewport(s);case"resume":return this.resumeViewport(s);case"enable":return this.enableViewport(s);case"openTreeNode":return this.openTreeNode(s,e);case"closeTreeNode":return this.closeTreeNode(s,e);case"createLink":return this.createLink(s,e);case"removeLink":return this.removeLink(s);case"setColumns":return this.setColumns(s,e);case"setTitle":return this.setTitle(s,e);default:}}else{if(Ce(e))return this.viewportRpcCall(e);if(me(e))return this.menuRpcCall(e);{let{type:s,requestId:n}=e;switch(s){case"GET_TABLE_LIST":{(t=this.tableList)!=null||(this.tableList=this.awaitResponseToMessage({type:s},n)),this.tableList.then(o=>{this.postMessageToClient({type:"TABLE_LIST_RESP",tables:o.tables,requestId:n})});return}case"GET_TABLE_META":{this.getTableMeta(e.table,n).then(o=>{o&&this.postMessageToClient({type:"TABLE_META_RESP",tableSchema:o,requestId:n})});return}case"RPC_CALL":return this.rpcCall(e);default:}}}M(\`Vuu ServerProxy Unexpected message from client \${JSON.stringify(e)}\`)}getTableMeta(e,t=C()){if(x(e))return Promise.resolve(void 0);let s=\`\${e.module}:\${e.table}\`,n=this.cachedTableMetaRequests.get(s);return n||(n=this.awaitResponseToMessage({type:"GET_TABLE_META",table:e},t),this.cachedTableMetaRequests.set(s,n)),n==null?void 0:n.then(o=>this.cacheTableMeta(o))}awaitResponseToMessage(e,t=C()){return new Promise((s,n)=>{this.sendMessageToServer(e,t),this.pendingRequests.set(t,{reject:n,resolve:s})})}sendIfReady(e,t,s=!0){return s&&this.sendMessageToServer(e,t),s}sendMessageToServer(e,t=\`\${We++}\`,s=mt){let{module:n="CORE"}=s;this.authToken&&this.connection.send({requestId:t,sessionId:this.sessionId,token:this.authToken,user:this.user,module:n,body:e})}handleMessageFromServer(e){var u;let{body:t,requestId:s,sessionId:n}=e,o=this.pendingRequests.get(s);if(o){let{resolve:a}=o;this.pendingRequests.delete(s),a(t);return}let{viewports:i}=this;switch(t.type){case Ie:this.sendMessageToServer({type:De,ts:+new Date},"NA");break;case"LOGIN_SUCCESS":if(n)this.sessionId=n,(u=this.pendingLogin)==null||u.resolve(n),this.pendingLogin=void 0;else throw Error("LOGIN_SUCCESS did not provide sessionId");break;case"REMOVE_VP_SUCCESS":{let a=i.get(t.viewPortId);a&&(this.mapClientToServerViewport.delete(a.clientViewportId),i.delete(t.viewPortId),this.removeViewportFromVisualLinks(t.viewPortId))}break;case xe:{let a=this.viewports.get(t.vpId);a&&a.completeOperation(s)}break;case Te:case ve:if(i.has(t.viewPortId)){let a=this.viewports.get(t.viewPortId);if(a){let l=a.completeOperation(s);l!==void 0&&(this.postMessageToClient(l),Q&&V(\`postMessageToClient \${JSON.stringify(l)}\`))}}break;case Me:{let a=this.viewports.get(t.viewPortId);if(a){let l=a.completeOperation(s);if(l){this.postMessageToClient(l);let[g,S]=a.resume();this.postMessageToClient({clientViewportId:a.clientViewportId,mode:"batch",rows:S,size:g,type:"viewport-update"})}}}break;case"TABLE_ROW":{let a=Se(t.rows);for(let[l,g]of Object.entries(a)){let S=i.get(l);S?S.updateRows(g):Y==null||Y(\`TABLE_ROW message received for non registered viewport \${l}\`)}this.processUpdates()}break;case"CHANGE_VP_RANGE_SUCCESS":{let a=this.viewports.get(t.viewPortId);if(a){let{from:l,to:g}=t;a.completeOperation(s,l,g)}}break;case ke:case Ee:break;case"CREATE_VISUAL_LINK_SUCCESS":{let a=this.viewports.get(t.childVpId),l=this.viewports.get(t.parentVpId);if(a&&l){let{childColumnName:g,parentColumnName:S}=t,I=a.completeOperation(s,g,l.clientViewportId,S);I&&this.postMessageToClient(I)}}break;case"REMOVE_VISUAL_LINK_SUCCESS":{let a=this.viewports.get(t.childVpId);if(a){let l=a.completeOperation(s);l&&this.postMessageToClient(l)}}break;case"VP_VISUAL_LINKS_RESP":{let a=this.getActiveLinks(t.links),l=this.viewports.get(t.vpId);if(a.length&&l){let g=Tt(a,this.viewports),[S,I]=l.setLinks(g);if(this.postMessageToClient(S),I){let{link:ne,parentClientVpId:Ke}=I,re=C(),oe=this.mapClientToServerViewport.get(Ke);if(oe){let Je=l.createLink(re,ne.fromColumn,oe,ne.toColumn);this.sendMessageToServer(Je,re)}}}}break;case"VIEW_PORT_MENUS_RESP":if(t.menu.name){let a=this.viewports.get(t.vpId);if(a){let l=a.setMenu(t.menu);this.postMessageToClient(l)}}break;case"VP_EDIT_RPC_RESPONSE":this.postMessageToClient({action:t.action,requestId:s,rpcName:t.rpcName,type:"VP_EDIT_RPC_RESPONSE"});break;case"VP_EDIT_RPC_REJECT":this.viewports.get(t.vpId)&&this.postMessageToClient({requestId:s,type:"VP_EDIT_RPC_REJECT",error:t.error});break;case"VIEW_PORT_MENU_REJ":{console.log("send menu error back to client");let{error:a,rpcName:l,vpId:g}=t,S=this.viewports.get(g);S&&this.postMessageToClient({clientViewportId:S.clientViewportId,error:a,rpcName:l,type:"VIEW_PORT_MENU_REJ",requestId:s});break}case"VIEW_PORT_MENU_RESP":if(fe(t)){let{action:a,rpcName:l}=t;this.awaitResponseToMessage({type:"GET_TABLE_META",table:a.table}).then(g=>{let S=H(g);this.postMessageToClient({rpcName:l,type:"VIEW_PORT_MENU_RESP",action:{...a,tableSchema:S},tableAlreadyOpen:this.isTableOpen(a.table),requestId:s})})}else{let{action:a}=t;this.postMessageToClient({type:"VIEW_PORT_MENU_RESP",action:a||Rt,tableAlreadyOpen:a!==null&&this.isTableOpen(a.table),requestId:s})}break;case"RPC_RESP":{let{method:a,result:l}=t;this.postMessageToClient({type:"RPC_RESP",method:a,result:l,requestId:s})}break;case"VIEW_PORT_RPC_REPONSE":{let{method:a,action:l}=t;this.postMessageToClient({type:"VIEW_PORT_RPC_RESPONSE",rpcName:a,action:l,requestId:s})}break;case"ERROR":M(t.msg);break;default:ft&&T(\`handleMessageFromServer \${t.type}.\`)}}cacheTableMeta(e){let{module:t,table:s}=e.table,n=\`\${t}:\${s}\`,o=this.cachedTableSchemas.get(n);return o||(o=H(e),this.cachedTableSchemas.set(n,o)),o}isTableOpen(e){if(e){let t=e.table;for(let s of this.viewports.values())if(!s.suspended&&s.table.table===t)return!0}}getActiveLinks(e){return e.filter(t=>{let s=this.viewports.get(t.parentVpId);return s&&!s.suspended})}processUpdates(){this.viewports.forEach(e=>{var t;if(e.hasUpdatesToProcess){let s=e.getClientRows();if(s!==W){let[n,o]=s,i=e.getNewRowCount();(i!==void 0||n&&n.length>0)&&(Q&&V(\`postMessageToClient #\${e.clientViewportId} viewport-update \${o}, \${(t=n==null?void 0:n.length)!=null?t:"no"} rows, size \${i}\`),o&&this.postMessageToClient({clientViewportId:e.clientViewportId,mode:o,rows:n,size:i,type:"viewport-update"}))}}})}};var{debug:us,debugEnabled:ls,error:qe,info:E,infoEnabled:bt,warn:_}=b("websocket-connection"),Fe="ws",Et=r=>r.startsWith(Fe+"://")||r.startsWith(Fe+"s://"),Ge={},X=Symbol("setWebsocket"),B=Symbol("connectionCallback");async function ze(r,e,t,s=10,n=5){return Ge[r]={status:"connecting",connect:{allowed:n,remaining:n},reconnect:{allowed:s,remaining:s}},He(r,e,t)}async function Z(r){throw Error("connection broken")}async function He(r,e,t,s){let{status:n,connect:o,reconnect:i}=Ge[r],u=n==="connecting"?o:i;try{t({type:"connection-status",status:"connecting"});let c=typeof s<"u",p=await Vt(r,e);console.info("%c\u26A1 %cconnected","font-size: 24px;color: green;font-weight: bold;","color:green; font-size: 14px;"),s!==void 0&&s[X](p);let a=s!=null?s:new ee(p,r,e,t),l=c?"reconnected":"connection-open-awaiting-session";return t({type:"connection-status",status:l}),a.status=l,u.remaining=u.allowed,a}catch{let p=--u.remaining>0;if(t({type:"connection-status",status:"disconnected",reason:"failed to connect",retry:p}),p)return wt(r,e,t,s,2e3);throw Error("Failed to establish connection")}}var wt=(r,e,t,s,n)=>new Promise(o=>{setTimeout(()=>{o(He(r,e,t,s))},n)}),Vt=(r,e)=>new Promise((t,s)=>{let n=Et(r)?r:\`wss://\${r}\`;bt&&e!==void 0&&E(\`WebSocket Protocol \${e==null?void 0:e.toString()}\`);let o=new WebSocket(n,e);o.onopen=()=>t(o),o.onerror=i=>s(i)}),Be=()=>{_==null||_("Connection cannot be closed, socket not yet opened")},\$e=r=>{_==null||_(\`Message cannot be sent, socket closed \${r.body.type}\`)},vt=r=>{try{return JSON.parse(r)}catch{throw Error(\`Error parsing JSON response from server \${r}\`)}},ee=class{constructor(e,t,s,n){this.close=Be;this.requiresLogin=!0;this.send=\$e;this.status="ready";this.messagesCount=0;this.connectionMetricsInterval=null;this.handleWebsocketMessage=e=>{let t=vt(e.data);this.messagesCount+=1,this[B](t)};this.url=t,this.protocol=s,this[B]=n,this[X](e)}reconnect(){Z(this)}[(B,X)](e){let t=this[B];e.onmessage=o=>{this.status="connected",e.onmessage=this.handleWebsocketMessage,this.handleWebsocketMessage(o)},this.connectionMetricsInterval=setInterval(()=>{t({type:"connection-metrics",messagesLength:this.messagesCount}),this.messagesCount=0},2e3),e.onerror=()=>{qe("\u26A1 connection error"),t({type:"connection-status",status:"disconnected",reason:"error"}),this.connectionMetricsInterval&&(clearInterval(this.connectionMetricsInterval),this.connectionMetricsInterval=null),this.status==="connection-open-awaiting-session"?qe("Websocket connection lost before Vuu session established, check websocket configuration"):this.status!=="closed"&&(Z(this),this.send=n)},e.onclose=()=>{E==null||E("\u26A1 connection close"),t({type:"connection-status",status:"disconnected",reason:"close"}),this.connectionMetricsInterval&&(clearInterval(this.connectionMetricsInterval),this.connectionMetricsInterval=null),this.status!=="closed"&&(Z(this),this.send=n)};let s=o=>{e.send(JSON.stringify(o))},n=o=>{E==null||E(\`TODO queue message until websocket reconnected \${o.body.type}\`)};this.send=s,this.close=()=>{this.status="closed",e.close(),this.close=Be,this.send=\$e,E==null||E("close websocket")}}};var v,{info:te,infoEnabled:se}=b("worker");async function yt(r,e,t,s,n,o,i){let u=await ze(r,e,c=>{de(c)?postMessage({type:"connection-metrics",messages:c}):pe(c)?(n(c),c.status==="reconnected"&&v.reconnect()):v.handleMessageFromServer(c)},o,i);v=new F(u,c=>Mt(c)),u.requiresLogin&&await v.login(t,s)}function Mt(r){postMessage(r)}var _t=async({data:r})=>{switch(r.type){case"connect":await yt(r.url,r.protocol,r.token,r.username,postMessage,r.retryLimitDisconnect,r.retryLimitStartup),postMessage({type:"connected"});break;case"subscribe":se&&te(\`client subscribe: \${JSON.stringify(r)}\`),v.subscribe(r);break;case"unsubscribe":se&&te(\`client unsubscribe: \${JSON.stringify(r)}\`),v.unsubscribe(r.viewport);break;default:se&&te(\`client message: \${JSON.stringify(r)}\`),v.handleMessageFromClient(r)}};self.addEventListener("message",_t);postMessage({type:"ready"}); + +`; \ No newline at end of file diff --git a/vuu-ui/packages/vuu-data/src/message-utils.ts b/vuu-ui/packages/vuu-data-remote/src/message-utils.ts similarity index 76% rename from vuu-ui/packages/vuu-data/src/message-utils.ts rename to vuu-ui/packages/vuu-data-remote/src/message-utils.ts index c01d27e17..07647817e 100644 --- a/vuu-ui/packages/vuu-data/src/message-utils.ts +++ b/vuu-ui/packages/vuu-data-remote/src/message-utils.ts @@ -1,13 +1,17 @@ +import { + SchemaColumn, + TableSchema, + VuuUIMessageOut, + WithRequestId, +} from "@finos/vuu-data-types"; import { ClientToServerMenuRPC, ClientToServerViewportRpcCall, - VuuColumnDataType, VuuRow, VuuRpcRequest, VuuTable, VuuTableMeta, } from "@finos/vuu-protocol-types"; -import { VuuUIMessageOut } from "./vuuUIMessageTypes"; const MENU_RPC_TYPES = [ "VIEW_PORT_MENUS_SELECT_RPC", @@ -35,8 +39,6 @@ export const isVuuRpcRequest = ( ): message is ClientToServerViewportRpcCall => message["type"] === "VIEW_PORT_RPC_CALL"; -export type WithRequestId = T & { requestId: string }; - export const stripRequestId = ({ requestId, ...rest @@ -68,38 +70,10 @@ export const groupRowsByViewport = (rows: VuuRow[]): ViewportRowMap => { return result; }; -export type SchemaColumn = { - name: string; - serverDataType: VuuColumnDataType; -}; - export interface VuuTableMetaWithTable extends VuuTableMeta { table: VuuTable; } -export type TableSchema = { - columns: SchemaColumn[]; - key: string; - table: VuuTable; -}; - -// Sort TableScheas by module -export const byModule = (schema1: TableSchema, schema2: TableSchema) => { - const m1 = schema1.table.module.toLowerCase(); - const m2 = schema2.table.module.toLowerCase(); - if (m1 < m2) { - return -1; - } else if (m1 > m2) { - return 1; - } else if (schema1.table.table < schema2.table.table) { - return -1; - } else if (schema1.table.table > schema2.table.table) { - return 1; - } else { - return 0; - } -}; - export const getColumnByName = ( schema: TableSchema, name?: string diff --git a/vuu-ui/packages/vuu-data/src/server-proxy/array-backed-moving-window.ts b/vuu-ui/packages/vuu-data-remote/src/server-proxy/array-backed-moving-window.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/server-proxy/array-backed-moving-window.ts rename to vuu-ui/packages/vuu-data-remote/src/server-proxy/array-backed-moving-window.ts diff --git a/vuu-ui/packages/vuu-data/src/server-proxy/messages.ts b/vuu-ui/packages/vuu-data-remote/src/server-proxy/messages.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/server-proxy/messages.ts rename to vuu-ui/packages/vuu-data-remote/src/server-proxy/messages.ts diff --git a/vuu-ui/packages/vuu-data/src/server-proxy/rpc-services.ts b/vuu-ui/packages/vuu-data-remote/src/server-proxy/rpc-services.ts similarity index 100% rename from vuu-ui/packages/vuu-data/src/server-proxy/rpc-services.ts rename to vuu-ui/packages/vuu-data-remote/src/server-proxy/rpc-services.ts diff --git a/vuu-ui/packages/vuu-data/src/server-proxy/server-proxy.ts b/vuu-ui/packages/vuu-data-remote/src/server-proxy/server-proxy.ts similarity index 98% rename from vuu-ui/packages/vuu-data/src/server-proxy/server-proxy.ts rename to vuu-ui/packages/vuu-data-remote/src/server-proxy/server-proxy.ts index 0af1dc051..b346c62c1 100644 --- a/vuu-ui/packages/vuu-data/src/server-proxy/server-proxy.ts +++ b/vuu-ui/packages/vuu-data-remote/src/server-proxy/server-proxy.ts @@ -1,40 +1,11 @@ -import { - ClientToServerBody, - ClientToServerMenuRPC, - ClientToServerMessage, - ClientToServerViewportRpcCall, - LinkDescriptorWithLabel, - ServerToClientCreateViewPortSuccess, - ServerToClientMessage, - ServerToClientTableList, - ServerToClientTableMeta, - VuuLinkDescriptor, - VuuRpcRequest, - VuuTable, -} from "@finos/vuu-protocol-types"; -import { logger, partition } from "@finos/vuu-utils"; -import { Connection } from "../connectionTypes"; import { DataSourceCallbackMessage, DataSourceVisualLinkCreatedMessage, DataSourceVisualLinkRemovedMessage, -} from "../data-source"; -import { - createSchemaFromTableMetadata, - groupRowsByViewport, - isVuuMenuRpcRequest, - isVuuRpcRequest, - stripRequestId, - TableSchema, - WithRequestId, -} from "../message-utils"; -import { - isSessionTable, - isSessionTableActionMessage, - isViewporttMessage as isViewportMessage, NoAction, OpenDialogAction, ServerProxySubscribeMessage, + TableSchema, VuuUIMessageIn, VuuUIMessageOut, VuuUIMessageOutAggregate, @@ -52,7 +23,32 @@ import { VuuUIMessageOutSubscribe, VuuUIMessageOutUnsubscribe, VuuUIMessageOutViewRange, -} from "../vuuUIMessageTypes"; + WithRequestId, +} from "@finos/vuu-data-types"; +import { + ClientToServerBody, + ClientToServerMenuRPC, + ClientToServerMessage, + ClientToServerViewportRpcCall, + LinkDescriptorWithLabel, + ServerToClientCreateViewPortSuccess, + ServerToClientMessage, + ServerToClientTableList, + ServerToClientTableMeta, + VuuLinkDescriptor, + VuuRpcRequest, + VuuTable, +} from "@finos/vuu-protocol-types"; +import { isViewporttMessage, logger, partition } from "@finos/vuu-utils"; +import { Connection } from "../connectionTypes"; +import { isSessionTable, isSessionTableActionMessage } from "../data-source"; +import { + createSchemaFromTableMetadata, + groupRowsByViewport, + isVuuMenuRpcRequest, + isVuuRpcRequest, + stripRequestId, +} from "../message-utils"; import * as Message from "./messages"; import { getRpcServiceModule } from "./rpc-services"; import { NO_DATA_UPDATE, Viewport } from "./viewport"; @@ -622,7 +618,7 @@ export class ServerProxy { | WithRequestId | WithRequestId ) { - if (isViewportMessage(message)) { + if (isViewporttMessage(message)) { if (message.type === "disable") { // Viewport may already have been unsubscribed const viewport = this.getViewportForClient(message.viewport, false); @@ -670,9 +666,11 @@ export class ServerProxy { } } } else if (isVuuRpcRequest(message)) { - return this.viewportRpcCall(message); + return this.viewportRpcCall( + message as WithRequestId + ); } else if (isVuuMenuRpcRequest(message)) { - return this.menuRpcCall(message); + return this.menuRpcCall(message as WithRequestId); } else { const { type, requestId } = message; switch (type) { diff --git a/vuu-ui/packages/vuu-data/src/server-proxy/viewport.ts b/vuu-ui/packages/vuu-data-remote/src/server-proxy/viewport.ts similarity index 99% rename from vuu-ui/packages/vuu-data/src/server-proxy/viewport.ts rename to vuu-ui/packages/vuu-data-remote/src/server-proxy/viewport.ts index 286c38ca9..be38e4c95 100644 --- a/vuu-ui/packages/vuu-data/src/server-proxy/viewport.ts +++ b/vuu-ui/packages/vuu-data-remote/src/server-proxy/viewport.ts @@ -1,5 +1,29 @@ -import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; -import { Selection } from "@finos/vuu-table-types"; +import { + DataSourceFilter, + DataSourceRow, + DataSourceAggregateMessage, + DataSourceCallbackMessage, + DataSourceColumnsMessage, + DataSourceDebounceRequest, + DataSourceDisabledMessage, + DataSourceEnabledMessage, + DataSourceFilterMessage, + DataSourceGroupByMessage, + DataSourceMenusMessage, + DataSourceSetConfigMessage, + DataSourceSortMessage, + DataSourceSubscribedMessage, + DataSourceVisualLinkCreatedMessage, + DataSourceVisualLinkRemovedMessage, + DataSourceVisualLinksMessage, + DataUpdateMode, + Selection, + TableSchema, + WithFullConfig, + ServerProxySubscribeMessage, + VuuUIMessageOutOpenTreeNode, + VuuUIMessageOutCloseTreeNode, +} from "@finos/vuu-data-types"; import { ClientToServerChangeViewPort, ClientToServerCloseTreeNode, @@ -29,31 +53,7 @@ import { logger, RangeMonitor, } from "@finos/vuu-utils"; -import { - DataSourceAggregateMessage, - DataSourceCallbackMessage, - DataSourceColumnsMessage, - DataSourceDebounceRequest, - DataSourceDisabledMessage, - DataSourceEnabledMessage, - DataSourceFilterMessage, - DataSourceGroupByMessage, - DataSourceMenusMessage, - DataSourceSetConfigMessage, - DataSourceSortMessage, - DataSourceSubscribedMessage, - DataSourceVisualLinkCreatedMessage, - DataSourceVisualLinkRemovedMessage, - DataSourceVisualLinksMessage, - DataUpdateMode, - WithFullConfig, -} from "../data-source"; -import { getFirstAndLastRows, TableSchema } from "../message-utils"; -import { - ServerProxySubscribeMessage, - VuuUIMessageOutCloseTreeNode, - VuuUIMessageOutOpenTreeNode, -} from "../vuuUIMessageTypes"; +import { getFirstAndLastRows } from "../message-utils"; import { ArrayBackedMovingWindow } from "./array-backed-moving-window"; import * as Message from "./messages"; diff --git a/vuu-ui/packages/vuu-data/src/remote-data-source.ts b/vuu-ui/packages/vuu-data-remote/src/vuu-data-source.ts similarity index 97% rename from vuu-ui/packages/vuu-data/src/remote-data-source.ts rename to vuu-ui/packages/vuu-data-remote/src/vuu-data-source.ts index 119b690c3..5f5558ea8 100644 --- a/vuu-ui/packages/vuu-data/src/remote-data-source.ts +++ b/vuu-ui/packages/vuu-data-remote/src/vuu-data-source.ts @@ -1,5 +1,20 @@ -import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; -import { Selection } from "@finos/vuu-table-types"; +import { + DataSource, + DataSourceCallbackMessage, + DataSourceConfig, + DataSourceConstructorProps, + DataSourceEvents, + DataSourceFilter, + DataSourceRow, + DataSourceStatus, + OptimizeStrategy, + RpcResponse, + Selection, + SubscribeCallback, + SubscribeProps, + TableSchema, + WithFullConfig, +} from "@finos/vuu-data-types"; import { ClientToServerEditRpc, ClientToServerMenuRPC, @@ -17,50 +32,34 @@ import { import { parseFilter } from "@finos/vuu-filter-parser"; import { + configChanged, debounce, EventEmitter, + isViewportMenusAction, + isVisualLinksAction, itemsOrOrderChanged, logger, metadataKeys, throttle, uuid, -} from "@finos/vuu-utils"; -import { getServerAPI, ServerAPI } from "./connection-manager"; -import { - configChanged, - DataSource, - DataSourceCallbackMessage, - DataSourceConfig, - DataSourceConstructorProps, - DataSourceEvents, - DataSourceStatus, - isDataSourceConfigMessage, - OptimizeStrategy, - RpcResponse, - SubscribeCallback, - SubscribeProps, vanillaConfig, withConfigDefaults, - WithFullConfig, -} from "./data-source"; +} from "@finos/vuu-utils"; +import { getServerAPI, ServerAPI } from "./connection-manager"; +import { isDataSourceConfigMessage } from "./data-source"; -import { - isViewportMenusAction, - isVisualLinksAction, - MenuRpcResponse, -} from "./vuuUIMessageTypes"; -import { TableSchema } from "./message-utils"; +import { MenuRpcResponse } from "@finos/vuu-data-types"; type RangeRequest = (range: VuuRange) => void; -const { info } = logger("RemoteDataSource"); +const { info } = logger("VuuDataSource"); const { KEY } = metadataKeys; /*----------------------------------------------------------------- A RemoteDataSource manages a single subscription via the ServerProxy ----------------------------------------------------------------*/ -export class RemoteDataSource +export class VuuDataSource extends EventEmitter implements DataSource { diff --git a/vuu-ui/packages/vuu-data/src/websocket-connection.ts b/vuu-ui/packages/vuu-data-remote/src/websocket-connection.ts similarity index 98% rename from vuu-ui/packages/vuu-data/src/websocket-connection.ts rename to vuu-ui/packages/vuu-data-remote/src/websocket-connection.ts index 604138cbd..96c311405 100644 --- a/vuu-ui/packages/vuu-data/src/websocket-connection.ts +++ b/vuu-ui/packages/vuu-data-remote/src/websocket-connection.ts @@ -4,12 +4,12 @@ import { } from "@finos/vuu-protocol-types"; import { Connection } from "./connectionTypes"; import { logger } from "@finos/vuu-utils"; - import { ConnectionQualityMetrics, ConnectionStatus, ConnectionStatusMessage, -} from "./vuuUIMessageTypes"; + WebSocketProtocol, +} from "@finos/vuu-data-types"; export type ConnectionMessage = | ServerToClientMessage @@ -17,8 +17,6 @@ export type ConnectionMessage = | ConnectionQualityMetrics; export type ConnectionCallback = (msg: ConnectionMessage) => void; -export type WebSocketProtocol = string | string[] | undefined; - const { debug, debugEnabled, error, info, infoEnabled, warn } = logger( "websocket-connection" ); diff --git a/vuu-ui/packages/vuu-data/src/worker.ts b/vuu-ui/packages/vuu-data-remote/src/worker.ts similarity index 94% rename from vuu-ui/packages/vuu-data/src/worker.ts rename to vuu-ui/packages/vuu-data-remote/src/worker.ts index 0bab408d7..540e3aa83 100644 --- a/vuu-ui/packages/vuu-data/src/worker.ts +++ b/vuu-ui/packages/vuu-data-remote/src/worker.ts @@ -1,20 +1,20 @@ -import { - connect as connectWebsocket, - WebSocketProtocol, -} from "./websocket-connection"; -import { ServerProxy } from "./server-proxy/server-proxy"; import { ConnectionStatusMessage, - isConnectionQualityMetrics, - isConnectionStatusMessage, VuuUIMessageOut, -} from "./vuuUIMessageTypes"; + WebSocketProtocol, + WithRequestId, +} from "@finos/vuu-data-types"; import { ClientToServerMenuRPC, VuuRpcRequest, } from "@finos/vuu-protocol-types"; -import { WithRequestId } from "./message-utils"; -import { logger } from "@finos/vuu-utils"; +import { + isConnectionQualityMetrics, + isConnectionStatusMessage, + logger, +} from "@finos/vuu-utils"; +import { ServerProxy } from "./server-proxy/server-proxy"; +import { connect as connectWebsocket } from "./websocket-connection"; let server: ServerProxy; diff --git a/vuu-ui/packages/vuu-data/test/array-backed-moving-window.test.js b/vuu-ui/packages/vuu-data-remote/test/array-backed-moving-window.test.js similarity index 100% rename from vuu-ui/packages/vuu-data/test/array-backed-moving-window.test.js rename to vuu-ui/packages/vuu-data-remote/test/array-backed-moving-window.test.js diff --git a/vuu-ui/packages/vuu-data/test/global-mocks.ts b/vuu-ui/packages/vuu-data-remote/test/global-mocks.ts similarity index 100% rename from vuu-ui/packages/vuu-data/test/global-mocks.ts rename to vuu-ui/packages/vuu-data-remote/test/global-mocks.ts diff --git a/vuu-ui/packages/vuu-data/test/message-utils.test.ts b/vuu-ui/packages/vuu-data-remote/test/message-utils.test.ts similarity index 100% rename from vuu-ui/packages/vuu-data/test/message-utils.test.ts rename to vuu-ui/packages/vuu-data-remote/test/message-utils.test.ts diff --git a/vuu-ui/packages/vuu-data/test/remote-data-source.test.ts b/vuu-ui/packages/vuu-data-remote/test/remote-data-source.test.ts similarity index 92% rename from vuu-ui/packages/vuu-data/test/remote-data-source.test.ts rename to vuu-ui/packages/vuu-data-remote/test/remote-data-source.test.ts index 8c956e6c9..6be4c4d21 100644 --- a/vuu-ui/packages/vuu-data/test/remote-data-source.test.ts +++ b/vuu-ui/packages/vuu-data-remote/test/remote-data-source.test.ts @@ -4,9 +4,9 @@ import "./global-mocks"; import { beforeEach, describe, expect, it, vi } from "vitest"; import * as connectionExports from "../src/connection-manager"; //---------------------------------------------------- +import { DataSourceConfig } from "@finos/vuu-data-types"; import { LinkDescriptorWithLabel, VuuSortCol } from "@finos/vuu-protocol-types"; -import { RemoteDataSource } from "../src/remote-data-source"; -import { DataSourceConfig } from "../src/data-source"; +import { VuuDataSource } from "../src/vuu-data-source"; const defaultSubscribeOptions = { aggregations: [], @@ -30,7 +30,7 @@ describe("RemoteDataSource", () => { it("cannot be created without table", () => { try { // @ts-ignore - new RemoteDataSource(); + new VuuDataSource(); throw Error("RemoteDataSource was created without table"); } catch (err) { expect(err).toBeDefined(); @@ -40,7 +40,7 @@ describe("RemoteDataSource", () => { } try { // @ts-ignore - new RemoteDataSource({}); + new VuuDataSource({}); throw Error("RemoteDataSource was created without table"); } catch (err) { expect(err).toBeDefined(); @@ -50,7 +50,7 @@ describe("RemoteDataSource", () => { } try { // @ts-ignore - new RemoteDataSource({ + new VuuDataSource({ bufferSize: 100, aggregations: [], columns: ["test1", "test2"], @@ -64,7 +64,7 @@ describe("RemoteDataSource", () => { }); it("requires only Table for successful construction", () => { - const dataSource = new RemoteDataSource({ + const dataSource = new VuuDataSource({ table: { module: "SIMUL", table: "instruments" }, }); expect(dataSource).toBeDefined(); @@ -76,7 +76,7 @@ describe("RemoteDataSource", () => { const sort = { sortDefs: [{ column: "col1", sortType: "A" } as VuuSortCol], }; - const dataSource = new RemoteDataSource({ + const dataSource = new VuuDataSource({ columns, filter, sort, @@ -102,7 +102,7 @@ describe("RemoteDataSource", () => { }); }) ); - const dataSource = new RemoteDataSource({ table }); + const dataSource = new VuuDataSource({ table }); await dataSource.subscribe({}, callback); expect(serverSubscribe).toHaveBeenCalledWith( @@ -126,7 +126,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => resolvedPromise ); - const dataSource = new RemoteDataSource({ table }); + const dataSource = new VuuDataSource({ table }); await dataSource.subscribe({}, callback); @@ -152,7 +152,7 @@ describe("RemoteDataSource", () => { }); vi.spyOn(connectionExports, "getServerAPI").mockImplementation(() => pr); - const dataSource = new RemoteDataSource({ table }); + const dataSource = new VuuDataSource({ table }); setTimeout(() => resolvePromise({ subscribe: serverSubscribe }), 50); @@ -195,7 +195,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => resolvedPromise ); - const dataSource = new RemoteDataSource({ + const dataSource = new VuuDataSource({ aggregations, bufferSize: 200, columns, @@ -247,7 +247,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => resolvedPromise ); - const dataSource = new RemoteDataSource({ + const dataSource = new VuuDataSource({ aggregations, columns, filter, @@ -298,7 +298,7 @@ describe("RemoteDataSource", () => { }); vi.spyOn(connectionExports, "getServerAPI").mockImplementation(() => pr); - const dataSource = new RemoteDataSource({ table }); + const dataSource = new VuuDataSource({ table }); setTimeout(() => { // dataSource is blocked inside subscribe function, awaiting server ... @@ -336,7 +336,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); const range = { from: 0, to: 20 }; @@ -354,7 +354,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); const aggregations = [{ column: "col1", aggType: 1 } as const]; @@ -373,7 +373,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); const columns = ["col1", "col2"]; @@ -391,7 +391,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); const filter = { filter: 'exchange="SETS"' }; @@ -409,7 +409,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); const groupBy = ["col1", "col2"]; @@ -428,7 +428,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); let config: DataSourceConfig = { @@ -474,7 +474,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); const config: DataSourceConfig = { @@ -509,7 +509,7 @@ describe("RemoteDataSource", () => { // @ts-ignore () => Promise.resolve({ send: serverSend, subscribe: callback }) ); - const dataSource = new RemoteDataSource({ table, viewport: "vp1" }); + const dataSource = new VuuDataSource({ table, viewport: "vp1" }); await dataSource.subscribe({}, callback); const config: DataSourceConfig = { diff --git a/vuu-ui/packages/vuu-data/test/server-proxy-throttle.test.ts b/vuu-ui/packages/vuu-data-remote/test/server-proxy-throttle.test.ts similarity index 60% rename from vuu-ui/packages/vuu-data/test/server-proxy-throttle.test.ts rename to vuu-ui/packages/vuu-data-remote/test/server-proxy-throttle.test.ts index f7e7b7e7f..00f7a2720 100644 --- a/vuu-ui/packages/vuu-data/test/server-proxy-throttle.test.ts +++ b/vuu-ui/packages/vuu-data-remote/test/server-proxy-throttle.test.ts @@ -1,34 +1,13 @@ import "./global-mocks"; -import { describe, expect, vi, it } from "vitest"; -import { - ServerProxy, - TEST_setRequestId, -} from "../src/server-proxy/server-proxy"; -import { Viewport } from "../src/server-proxy/viewport"; +import { describe, vi, it } from "vitest"; +import { TEST_setRequestId } from "../src/server-proxy/server-proxy"; import { COMMON_ATTRS, - COMMON_ROW_ATTRS, COMMON_TABLE_ROW_ATTRS, createServerProxyAndSubscribeToViewport, createTableRows, - createTableGroupRows, - createSubscription, sizeRow, - updateTableRow, } from "./test-utils"; -import { - DataSourceDataMessage, - DataSourceEnabledMessage, - DataSourceSubscribedMessage, -} from "../src"; -import { VuuRow } from "@finos/vuu-protocol-types"; - -const SERVER_MESSAGE_CONSTANTS = { - module: "CORE", - sessionId: "dsdsd", - token: "test", - user: "user", -}; const mockConnection = { send: vi.fn(), diff --git a/vuu-ui/packages/vuu-data/test/server-proxy.test.ts b/vuu-ui/packages/vuu-data-remote/test/server-proxy.test.ts similarity index 100% rename from vuu-ui/packages/vuu-data/test/server-proxy.test.ts rename to vuu-ui/packages/vuu-data-remote/test/server-proxy.test.ts diff --git a/vuu-ui/packages/vuu-data/test/test-utils.ts b/vuu-ui/packages/vuu-data-remote/test/test-utils.ts similarity index 100% rename from vuu-ui/packages/vuu-data/test/test-utils.ts rename to vuu-ui/packages/vuu-data-remote/test/test-utils.ts diff --git a/vuu-ui/packages/vuu-data/test/viewport.test.ts b/vuu-ui/packages/vuu-data-remote/test/viewport.test.ts similarity index 100% rename from vuu-ui/packages/vuu-data/test/viewport.test.ts rename to vuu-ui/packages/vuu-data-remote/test/viewport.test.ts diff --git a/vuu-ui/packages/vuu-data/test/websocket-connection.test.ts b/vuu-ui/packages/vuu-data-remote/test/websocket-connection.test.ts similarity index 100% rename from vuu-ui/packages/vuu-data/test/websocket-connection.test.ts rename to vuu-ui/packages/vuu-data-remote/test/websocket-connection.test.ts diff --git a/vuu-ui/packages/vuu-data-remote/tsconfig.json b/vuu-ui/packages/vuu-data-remote/tsconfig.json new file mode 100644 index 000000000..db9582a16 --- /dev/null +++ b/vuu-ui/packages/vuu-data-remote/tsconfig.json @@ -0,0 +1,6 @@ +{ +"extends": "../../tsconfig.json", +"compilerOptions":{ + "composite": true +}, +} diff --git a/vuu-ui/packages/vuu-data-test/src/Table.ts b/vuu-ui/packages/vuu-data-test/src/Table.ts index c06f8eabc..f69981219 100644 --- a/vuu-ui/packages/vuu-data-test/src/Table.ts +++ b/vuu-ui/packages/vuu-data-test/src/Table.ts @@ -1,4 +1,4 @@ -import { SchemaColumn, TableSchema } from "@finos/vuu-data"; +import { SchemaColumn, TableSchema } from "@finos/vuu-data-types"; import { VuuRowDataItemType, VuuTable } from "@finos/vuu-protocol-types"; import { ColumnMap, EventEmitter } from "@finos/vuu-utils"; import { UpdateGenerator } from "./rowUpdates"; diff --git a/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts b/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts index 9432b3ed1..435bc6cd1 100644 --- a/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts +++ b/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts @@ -1,23 +1,22 @@ import { ArrayDataSource, - ArrayDataSourceConstructorProps, - MenuRpcResponse, - RpcResponse, + ArrayDataSourceConstructorProps +} from "@finos/vuu-data-local"; +import { + DataSourceRow, MenuRpcResponse, RpcResponse, + SelectionItem, SubscribeCallback, - SubscribeProps, - VuuUIMessageInRPCEditReject, - VuuUIMessageInRPCEditResponse, -} from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; + SubscribeProps, VuuUIMessageInRPCEditReject, + VuuUIMessageInRPCEditResponse +} from "@finos/vuu-data-types"; import { ClientToServerEditRpc, ClientToServerMenuRPC, ClientToServerViewportRpcCall, VuuMenu, VuuRange, - VuuRowDataItemType, + VuuRowDataItemType } from "@finos/vuu-protocol-types"; -import { SelectionItem } from "@finos/vuu-table-types"; import { metadataKeys } from "@finos/vuu-utils"; import { makeSuggestions } from "./makeSuggestions"; import { Table } from "./Table"; diff --git a/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts b/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts index 812496f02..37fe1c24d 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts @@ -133,10 +133,11 @@ async function addConstituent(rpcRequest: ClientToServerViewportRpcCall) { } async function sendToMarket(rpcRequest: ClientToServerViewportRpcCall) { const [basketInstanceId] = rpcRequest.params; - console.log(`RPC call erceived ${rpcRequest.rpcName} ${basketInstanceId}`); + basketTrading.update(basketInstanceId, "status", "ON_MARKET"); } async function takeOffMarket(rpcRequest: ClientToServerViewportRpcCall) { - console.log(`RPC call erceived ${rpcRequest.rpcName}`); + const [basketInstanceId] = rpcRequest.params; + basketTrading.update(basketInstanceId, "status", "OFF-MARKET"); } async function createNewBasket(rpcRequest: ClientToServerViewportRpcCall) { diff --git a/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts b/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts index b6e6d6274..122586490 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts @@ -1,4 +1,4 @@ -import { TableSchema } from "@finos/vuu-data"; +import { TableSchema } from "@finos/vuu-data-types"; export type BasketsTableName = | "algoType" diff --git a/vuu-ui/packages/vuu-data-test/src/basket/reference-data/constituents.ts b/vuu-ui/packages/vuu-data-test/src/basket/reference-data/constituents.ts index 82df44a61..6378d0135 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/reference-data/constituents.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/reference-data/constituents.ts @@ -2,7 +2,7 @@ import ftse from "./ftse100"; import nasdaq from "./nasdaq100"; import sp500 from "./sp500"; import hsi from "./hsi"; -import { VuuRowDataItemType } from "packages/vuu-protocol-types"; +import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; const basketConstituentData = []; for (const row of ftse) { diff --git a/vuu-ui/packages/vuu-data-test/src/schemas.ts b/vuu-ui/packages/vuu-data-test/src/schemas.ts index 79adf5250..c8d729305 100644 --- a/vuu-ui/packages/vuu-data-test/src/schemas.ts +++ b/vuu-ui/packages/vuu-data-test/src/schemas.ts @@ -1,4 +1,4 @@ -import { TableSchema } from "@finos/vuu-data"; +import { TableSchema } from "@finos/vuu-data-types"; import { type BasketsTableName, schemas as basketSchemas, diff --git a/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments-extended.ts b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments-extended.ts index 228455dc4..43cbed12c 100644 --- a/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments-extended.ts +++ b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments-extended.ts @@ -7,7 +7,7 @@ import { instrumentsData } from "./instruments"; const instrumentsExtendedData = instrumentsData.map((row) => (row as VuuRowDataItemType[]) .slice(0, -1) - .concat([random(0, 1) === 1, random(0, 1) === 1]) + .concat([random(0, 1) === 1, random(0, 1) === 1, new Date().getTime()]) ); const instrumentsExtendedTable = new Table( diff --git a/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts index e818d9d42..7f61d8ff8 100644 --- a/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts +++ b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts @@ -46,10 +46,10 @@ const randomPrice = () => { return price / multiplier; }; -const start = performance.now(); +// const start = performance.now(); // Create 10_000 Instruments for (const char of chars) { - for (let i = 0; i < 10_000; i++) { + for (let i = 0; i < 10_00; i++) { const char2 = chars[random(0, chars.length - 1)]; const char3 = chars[random(0, chars.length - 1)]; const char4 = chars[random(0, chars.length - 1)]; @@ -77,8 +77,8 @@ for (const char of chars) { ]); } } -const end = performance.now(); -console.log(`generating 10,000 instruments took ${end - start} ms`); +// const end = performance.now(); +// console.log(`generating 10,000 instruments took ${end - start} ms`); const instrumentsTable = new Table( schemas.instruments, diff --git a/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts b/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts index 35f4f29e9..17718f57f 100644 --- a/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts +++ b/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts @@ -1,5 +1,5 @@ -import type { TableSchema } from "@finos/vuu-data"; import type { ColumnDescriptor } from "@finos/vuu-table-types"; +import { TableSchema } from "@finos/vuu-data-types"; export type SimulTableName = | "instruments" @@ -38,6 +38,7 @@ export const schemas: Readonly>> = { name: "ric", serverDataType: "string" }, { name: "supported", serverDataType: "boolean" }, { name: "wishlist", serverDataType: "boolean" }, + { name: "lastUpdated", serverDataType: "long" }, ], key: "ric", table: { module: "SIMUL", table: "instruments" }, diff --git a/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts b/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts index 2e8386293..61f9c58d6 100644 --- a/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts +++ b/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts @@ -1,5 +1,5 @@ -import { DataSource } from "@finos/vuu-data"; -import { SuggestionFetcher } from "packages/vuu-data-react/src"; +import { DataSource } from "@finos/vuu-data-types"; +import { SuggestionFetcher } from "@finos/vuu-data-react"; import basketModule from "./basket/basket-module"; import { BasketsTableName } from "./basket/basket-schemas"; import simulModule from "./simul/simul-module"; diff --git a/vuu-ui/packages/vuu-data-types/index.d.ts b/vuu-ui/packages/vuu-data-types/index.d.ts index a0efbbfd7..abe5e071b 100644 --- a/vuu-ui/packages/vuu-data-types/index.d.ts +++ b/vuu-ui/packages/vuu-data-types/index.d.ts @@ -1,6 +1,36 @@ -import { VuuFilter, VuuRowDataItemType } from "@finos/vuu-protocol-types"; -import { Filter } from "@finos/vuu-filter-types"; -import { MenuActionClosePopup } from "@finos/vuu-popups"; +import type { Filter } from "@finos/vuu-filter-types"; +import type { MenuActionClosePopup } from "@finos/vuu-popups"; +import type { + ClientToServerEditRpc, + ClientToServerMenuRPC, + ClientToServerViewportRpcCall, + VuuAggregation, + VuuColumnDataType, + VuuColumns, + VuuDataRowDto, + VuuFilter, + VuuGroupBy, + VuuLinkDescriptor, + VuuMenu, + VuuRowDataItemType, + VuuSort, + VuuTable, +} from "@finos/vuu-protocol-types"; +import type { IEventEmitter } from "@finos/vuu-utils"; +import type { + DataSourceFilter, + MenuRpcResponse, + Selection, + TableSchema, +} from "@finos/vuu-data-types"; +import type { + ClientToServerTableList, + ClientToServerTableMeta, + LinkDescriptorWithLabel, + ServerToClientViewportRpcResponse, + TypeAheadMethod, + VuuRange, +} from "@finos/vuu-protocol-types"; export interface DataSourceFilter extends VuuFilter { filterStruct?: Filter; @@ -46,13 +76,155 @@ export interface ContextMenuLeafItemDescriptor extends ContextMenuItemBase { options?: unknown; } +export type ContextMenuItemDescriptor = + | ContextMenuLeafItemDescriptor + | ContextMenuGroupItemDescriptor; + export interface ContextMenuGroupItemDescriptor extends ContextMenuItemBase { children: ContextMenuItemDescriptor[]; } -export type ContextMenuItemDescriptor = - | ContextMenuLeafItemDescriptor - | ContextMenuGroupItemDescriptor; +export interface MessageWithClientViewportId { + clientViewportId: string; +} + +export interface DataSourceAggregateMessage + extends MessageWithClientViewportId { + aggregations: VuuAggregation[]; + type: "aggregate"; +} + +export type DataUpdateMode = "batch" | "update" | "size-only"; + +export interface DataSourceDataMessage extends MessageWithClientViewportId { + mode: DataUpdateMode; + rows?: DataSourceRow[]; + size?: number; + type: "viewport-update"; +} + +export interface DataSourceDataSizeMessage extends MessageWithClientViewportId { + mode: "size-only"; + size: number; + type: "viewport-update"; +} + +export interface DataSourceDisabledMessage extends MessageWithClientViewportId { + type: "disabled"; +} + +export interface DataSourceEnabledMessage extends MessageWithClientViewportId { + type: "enabled"; +} + +export interface DataSourceColumnsMessage extends MessageWithClientViewportId { + type: "columns"; + columns: VuuColumns; +} +export interface DataSourceFilterMessage extends MessageWithClientViewportId { + type: "filter"; + filter: DataSourceFilter; +} +export interface DataSourceGroupByMessage extends MessageWithClientViewportId { + type: "groupBy"; + groupBy: VuuGroupBy | undefined; +} + +export interface DataSourceSetConfigMessage + extends MessageWithClientViewportId { + type: "config"; + config: WithFullConfig; +} + +export interface DataSourceDebounceRequest extends MessageWithClientViewportId { + type: "debounce-begin"; +} + +export interface DataSourceMenusMessage extends MessageWithClientViewportId { + type: "vuu-menu"; + menu: VuuMenu; +} + +export interface DataSourceSortMessage extends MessageWithClientViewportId { + type: "sort"; + sort: VuuSort; +} + +export interface DataSourceSubscribedMessage + extends MessageWithClientViewportId { + aggregations: VuuAggregation[]; + columns: VuuColumns; + filter: DataSourceFilter; + groupBy: VuuGroupBy; + range: VuuRange; + sort: VuuSort; + tableSchema: Readonly; + type: "subscribed"; +} + +export interface DataSourceVisualLinkCreatedMessage + extends MessageWithClientViewportId { + colName: string; + parentViewportId: string; + parentColName: string; + type: "vuu-link-created"; +} + +export interface DataSourceVisualLinkRemovedMessage + extends MessageWithClientViewportId { + type: "vuu-link-removed"; +} + +export interface DataSourceVisualLinksMessage + extends MessageWithClientViewportId { + type: "vuu-links"; + links: VuuLinkDescriptor[]; +} + +export type VuuFeatureInvocationMessage = + | DataSourceVisualLinkCreatedMessage + | DataSourceVisualLinkRemovedMessage; + +export type VuuFeatureMessage = + | DataSourceMenusMessage + | DataSourceVisualLinksMessage; + +export type DataSourceConfigMessage = + | DataSourceAggregateMessage + | DataSourceColumnsMessage + | DataSourceFilterMessage + | DataSourceGroupByMessage + | DataSourceSortMessage + | DataSourceSetConfigMessage; + +export type DataSourceCallbackMessage = + | DataSourceConfigMessage + | DataSourceColumnsMessage + | DataSourceDataMessage + | DataSourceDebounceRequest + | DataSourceDisabledMessage + | DataSourceEnabledMessage + | DataSourceMenusMessage + | DataSourceSubscribedMessage + | DataSourceVisualLinkCreatedMessage + | DataSourceVisualLinkRemovedMessage + | DataSourceVisualLinksMessage; + +export type ConfigChangeColumnsMessage = { + type: "columns"; + columns?: ColumnDescriptor[]; +}; + +export type ConfigChangeMessage = + | ConfigChangeColumnsMessage + | DataSourceAggregateMessage + | DataSourceFilterMessage + | DataSourceGroupByMessage + | DataSourceSortMessage + | DataSourceVisualLinkCreatedMessage + | DataSourceVisualLinkRemovedMessage; + +export type ConfigChangeHandler = (msg: ConfigChangeMessage) => void; /** * MenuBuilder describes a factory function that creates @@ -82,3 +254,495 @@ export interface ContextMenuContextType { menuBuilders: MenuBuilder[]; menuActionHandler: MenuActionHandler; } + +export type SchemaColumn = { + name: string; + serverDataType: VuuColumnDataType; +}; + +export type TableSchema = { + columns: SchemaColumn[]; + key: string; + table: VuuTable; +}; + +/** + * Described the configuration values that should typically be + * persisted across sessions. + */ +export interface WithFullConfig { + readonly aggregations: VuuAggregation[]; + readonly columns: string[]; + readonly filter: DataSourceFilter; + readonly groupBy: VuuGroupBy; + readonly sort: VuuSort; + readonly visualLink?: LinkDescriptorWithLabel; +} + +export interface DataSourceConfig extends Partial { + visualLink?: LinkDescriptorWithLabel; +} + +export interface WithGroupBy extends DataSourceConfig { + groupBy: VuuGroupBy; +} +export interface WithFilter extends DataSourceConfig { + filter: DataSourceFilter; +} +export interface WithSort extends DataSourceConfig { + sort: VuuSort; +} + +export interface DataSourceConstructorProps extends DataSourceConfig { + bufferSize?: number; + table: VuuTable; + title?: string; + viewport?: string; +} + +export interface SubscribeProps { + viewport?: string; + columns?: string[]; + aggregations?: VuuAggregation[]; + range?: VuuRange; + sort?: VuuSort; + groupBy?: VuuGroupBy; + filter?: DataSourceFilter; + title?: string; +} + +export type SubscribeCallback = (message: DataSourceCallbackMessage) => void; +export type OptimizeStrategy = "none" | "throttle" | "debounce"; + +export type DataSourceEvents = { + config: (config: DataSourceConfig | undefined, confirmed?: boolean) => void; + optimize: (optimize: OptimizeStrategy) => void; + range: (range: VuuRange) => void; + resize: (size: number) => void; +}; + +/** + * return Promise indicates success + * return Promise indicates failure + */ +export type DataSourceEditHandler = ( + row: DataSourceRow, + columnName: string, + value: VuuRowDataItemType +) => Promise; + +export type DataSourceDeleteHandler = (key: string) => Promise; +export type DataSourceInsertHandler = ( + key: string, + data: VuuDataRowDto +) => Promise; + +export type RpcResponse = + | MenuRpcResponse + | VuuUIMessageInRPCEditReject + | VuuUIMessageInRPCEditResponse + | ViewportRpcResponse; + +export type RpcResponseHandler = (response: RpcResponse) => boolean; + +export type RowSearchPredicate = (row: DataSourceRow) => boolean; + +export type DataSourceStatus = + | "disabled" + | "disabling" + | "enabled" + | "enabling" + | "initialising" + | "subscribing" + | "subscribed" + | "suspended" + | "unsubscribed"; + +export interface TypeaheadSuggestionProvider { + getTypeaheadSuggestions: ( + columnName: string, + pattern?: string + ) => Promise; +} + +export type RangeTuple = [from: number, to: number]; +export type SelectionItem = number | RangeTuple; +export type Selection = SelectionItem[]; +export type SelectionChangeHandler = (selection: Selection) => void; + +export interface DataSource + extends IEventEmitter, + Partial { + aggregations: VuuAggregation[]; + applyEdit: DataSourceEditHandler; + /** + * set config without triggering config event. Use this method when initialising + * a dataSource that has been restored from session state. The dataSource will + * not yet be subscribed. Triggering the config event is unnecessary and might + * cause a React exception if the event were to cause a render. + * @param config DataSourceConfig + * @returns true if config has been applied (will not be if existig config is same) + */ + applyConfig: (config: DataSourceConfig) => true | undefined; + closeTreeNode: (key: string, cascade?: boolean) => void; + columns: string[]; + config: DataSourceConfig; + status: DataSourceStatus; + /** + * + * Similar to disable but intended for pauses of very short duration (default is 3 seconds). Although + * the dataSource will stop sending messages until resumed, it will not disconnect from a remote server. + * It will preserve subscription to the remote server and continue to apply updates to cached data. It + * just won't send updates through to the UI thread (until resumed). Useful in edge cases such as where a + * component is dragged to a new location. When dropped, the component will be unmounted and very quickly + * remounted by React. For the duration of this operation, we suspend updates . Updating an unmounted + * React component would cause a React error. + * If an suspend is requested and not resumed within 3 seconds, it will automatically be promoted to a disable., + */ + suspend?: () => void; + resume?: () => void; + + deleteRow?: DataSourceDeleteHandler; + + /** + * For a dataSource that has been previously disabled and is currently in disabled state , this will restore + * the subscription to active status. Fresh data will be dispatched to client. The enable call optionally + * accepts the same subscribe callback as subscribe. This allows a completely new instance of a component to + * assume ownership of a subscription and receive all messages. + */ + enable?: (callback?: SubscribeCallback) => void; + /** + * Disables this subscription. A datasource will send no further messages until re-enabled. Example usage + * might be for a component displayed within a set of Tabs. If user switches to another tab, the dataSource + * of the component that is no longer visible can be disabled until it is made visible again. + */ + disable?: () => void; + filter: DataSourceFilter; + + /** + * Only implemented on JSON DataSource + * @param depth + * @param visibleOnly + * @returns + */ + getChildRows?: (rowKey: string) => DataSourceRow[]; + /** + * Only implemented on JSON DataSource + * @param depth + * @param visibleOnly + * @returns + */ + getRowsAtDepth?: (depth: number, visibleOnly?: boolean) => DataSourceRow[]; + groupBy: VuuGroupBy; + insertRow?: DataSourceInsertHandler; + links?: LinkDescriptorWithLabel[]; + menu?: VuuMenu; + menuRpcCall: ( + rpcRequest: Omit | ClientToServerEditRpc + ) => Promise; + rpcCall?: ( + message: Omit + ) => Promise; + openTreeNode: (key: string) => void; + range: VuuRange; + select: SelectionChangeHandler; + readonly selectedRowsCount: number; + readonly size: number; + sort: VuuSort; + subscribe: ( + props: SubscribeProps, + callback: SubscribeCallback + ) => Promise; + table?: VuuTable; + readonly tableSchema?: TableSchema; + title?: string; + unsubscribe: () => void; + viewport?: string; + visualLink?: LinkDescriptorWithLabel; +} + +export interface MenuRpcResponse { + action: MenuRpcAction; + error?: string; + requestId: string; + rpcName?: string; + tableAlreadyOpen?: boolean; + type: "VIEW_PORT_MENU_RESP"; +} + +export interface OpenDialogAction { + type: "OPEN_DIALOG_ACTION"; + tableSchema?: TableSchema; + table?: VuuTable; +} +export interface NoAction { + type: "NO_ACTION"; +} + +export declare type MenuRpcAction = OpenDialogAction | NoAction; + +export type ConnectionStatus = + | "connecting" + | "connection-open-awaiting-session" + | "connected" + | "disconnected" + | "reconnected"; + +export interface ConnectionStatusMessage { + type: "connection-status"; + reason?: string; + retry?: boolean; + status: ConnectionStatus; +} + +export interface ConnectionQualityMetrics { + type: "connection-metrics"; + messagesLength: number; +} + +export interface ServerProxySubscribeMessage { + aggregations: VuuAggregation[]; + bufferSize?: number; + columns: VuuColumns; + filter: DataSourceFilter; + groupBy: VuuGroupBy; + range: VuuRange; + sort: VuuSort; + table: VuuTable; + title?: string; + viewport: string; + visualLink?: LinkDescriptorWithLabel; +} + +// export type VuuUIMessageInConnectionStatus = { +// type: 'connection-status'; +// }; + +export type VuuUIMessageInConnected = { + type: "connected"; +}; + +export type VuuUIMessageInWorkerReady = { + type: "ready"; +}; + +export interface ViewportMessageIn { + clientViewportId: string; +} + +// TODO use generic to type result +export interface VuuUIMessageInRPC { + method: string; + result: unknown; + requestId: string; + type: "RPC_RESP"; +} + +export interface VuuUIMessageInRPCEditReject { + error: string; + requestId?: string; + type: "VP_EDIT_RPC_REJECT"; +} + +export interface VuuUIMessageInRPCEditResponse { + action: unknown; + requestId: string; + rpcName: string; + type: "VP_EDIT_RPC_RESPONSE"; +} + +export interface VuuUIMessageInTableList { + requestId: string; + type: "TABLE_LIST_RESP"; + tables: VuuTable[]; +} +export interface VuuUIMessageInTableMeta { + requestId: string; + tableSchema: TableSchema; + type: "TABLE_META_RESP"; +} +export interface ViewportRpcResponse { + action: ServerToClientViewportRpcResponse["action"]; + requestId: string; + rpcName?: string; + type: "VIEW_PORT_RPC_RESPONSE"; +} +export interface MenuRpcReject extends ViewportMessageIn { + error?: string; + requestId: string; + rpcName?: string; + type: "VIEW_PORT_MENU_REJ"; +} + +export interface VuuUIMessageInMenuRej { + error: string; + requestId: string; + rpcName: string; + type: "VIEW_PORT_MENU_REJ"; +} + +export type VuuUIMessageIn = + | VuuUIMessageInConnected + | VuuUIMessageInWorkerReady + | VuuUIMessageInRPC + | ViewportRpcResponse + | MenuRpcResponse + | MenuRpcReject + | VuuUIMessageInTableList + | VuuUIMessageInTableMeta + | VuuUIMessageInRPCEditReject + | VuuUIMessageInRPCEditResponse; + +export type WebSocketProtocol = string | string[] | undefined; + +export interface VuuUIMessageOutConnect { + protocol: WebSocketProtocol; + type: "connect"; + token: string; + url: string; + username?: string; + retryLimitDisconnect?: number; + retryLimitStartup?: number; +} + +export interface VuuUIMessageOutSubscribe extends ServerProxySubscribeMessage { + type: "subscribe"; +} + +export interface VuuUIMessageOutUnsubscribe { + type: "unsubscribe"; + viewport: string; +} +export interface VuuUIMessageOutSuspend { + type: "suspend"; + viewport: string; +} +export interface VuuUIMessageOutResume { + type: "resume"; + viewport: string; +} + +export interface ViewportMessageOut { + viewport: string; +} + +export interface RequestMessage { + requestId: string; +} + +export interface VuuUIMessageOutColumns extends ViewportMessageOut { + type: "setColumns"; + columns: string[]; +} +export interface VuuUIMessageOutViewRange extends ViewportMessageOut { + type: "setViewRange"; + range: { + from: number; + to: number; + }; +} +export interface VuuUIMessageOutAggregate extends ViewportMessageOut { + aggregations: VuuAggregation[]; + type: "aggregate"; +} +export interface VuuUIMessageOutCloseTreeNode extends ViewportMessageOut { + key: string; + type: "closeTreeNode"; +} +export interface VuuUIMessageOutCreateLink extends ViewportMessageOut { + childColumnName: string; + parentColumnName: string; + parentClientVpId: string; + type: "createLink"; +} +export interface VuuUIMessageOutRemoveLink extends ViewportMessageOut { + type: "removeLink"; +} +export interface VuuUIMessageOutSetTitle extends ViewportMessageOut { + title: string; + type: "setTitle"; +} + +export interface VuuUIMessageOutDisable extends ViewportMessageOut { + type: "disable"; +} +export interface VuuUIMessageOutEnable extends ViewportMessageOut { + type: "enable"; +} +export interface VuuUIMessageOutOpenTreeNode extends ViewportMessageOut { + key: string; + type: "openTreeNode"; +} +export interface VuuUIMessageOutResume extends ViewportMessageOut { + type: "resume"; +} + +export interface VuuUIMessageOutSelect extends ViewportMessageOut { + selected: Selection; + type: "select"; +} +export interface VuuUIMessageOutSelectAll extends ViewportMessageOut { + type: "selectAll"; +} +export interface VuuUIMessageOutSelectNone extends ViewportMessageOut { + type: "selectNone"; +} + +export interface VuuUIMessageOutSort extends ViewportMessageOut { + sort: VuuSort; + type: "sort"; +} +export interface VuuUIMessageOutSuspend extends ViewportMessageOut { + type: "suspend"; +} + +export interface VuuUIMessageOutFilter extends ViewportMessageOut { + filter: DataSourceFilter; + type: "filter"; +} +export interface VuuUIMessageOutGroupby extends ViewportMessageOut { + groupBy: VuuGroupBy; + type: "groupBy"; +} + +export interface VuuUIMessageOutConfig extends ViewportMessageOut { + config: WithFullConfig; + type: "config"; +} + +export type VuuUIMessageOutViewport = + | VuuUIMessageOutAggregate + | VuuUIMessageOutCloseTreeNode + | VuuUIMessageOutColumns + | VuuUIMessageOutConfig + | VuuUIMessageOutCreateLink + | VuuUIMessageOutFilter + | VuuUIMessageOutDisable + | VuuUIMessageOutEnable + | VuuUIMessageOutGroupby + | VuuUIMessageOutOpenTreeNode + | VuuUIMessageOutRemoveLink + | VuuUIMessageOutResume + | VuuUIMessageOutSelect + | VuuUIMessageOutSelectAll + | VuuUIMessageOutSelectNone + | VuuUIMessageOutSetTitle + | VuuUIMessageOutSuspend + | VuuUIMessageOutSort + | VuuUIMessageOutViewRange; + +export interface TypeAheadRpcRequest { + method: TypeAheadMethod; + params: [VuuTable, ...string[]]; + type: "RPC_CALL"; +} + +export type WithRequestId = T & { requestId: string }; + +export type VuuUIMessageOut = + | VuuUIMessageOutConnect + | VuuUIMessageOutSubscribe + | VuuUIMessageOutUnsubscribe + | VuuUIMessageOutViewport + | WithRequestId + | WithRequestId; diff --git a/vuu-ui/packages/vuu-data/src/data-source.ts b/vuu-ui/packages/vuu-data/src/data-source.ts deleted file mode 100644 index 6fcd40d5e..000000000 --- a/vuu-ui/packages/vuu-data/src/data-source.ts +++ /dev/null @@ -1,604 +0,0 @@ -import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; -import { - ColumnDescriptor, - SelectionChangeHandler, -} from "@finos/vuu-table-types"; -import { - ClientToServerEditRpc, - ClientToServerMenuRPC, - ClientToServerViewportRpcCall, - LinkDescriptorWithLabel, - VuuAggregation, - VuuColumns, - VuuDataRowDto, - VuuFilter, - VuuGroupBy, - VuuLinkDescriptor, - VuuMenu, - VuuRange, - VuuRowDataItemType, - VuuSort, - VuuTable, -} from "@finos/vuu-protocol-types"; -import { EventEmitter } from "@finos/vuu-utils"; -import { TableSchema } from "./message-utils"; -import { - MenuRpcResponse, - ViewportRpcResponse, - VuuUIMessageInRPCEditReject, - VuuUIMessageInRPCEditResponse, -} from "./vuuUIMessageTypes"; - -export interface MessageWithClientViewportId { - clientViewportId: string; -} -// GridModelActions -export interface DataSourceAggregateMessage - extends MessageWithClientViewportId { - aggregations: VuuAggregation[]; - type: "aggregate"; -} - -export type DataUpdateMode = "batch" | "update" | "size-only"; -export interface DataSourceDataMessage extends MessageWithClientViewportId { - mode: DataUpdateMode; - rows?: DataSourceRow[]; - size?: number; - type: "viewport-update"; -} - -export interface DataSourceDataSizeMessage extends MessageWithClientViewportId { - mode: "size-only"; - size: number; - type: "viewport-update"; -} - -export interface DataSourceDebounceRequest extends MessageWithClientViewportId { - type: "debounce-begin"; -} - -export const isSizeOnly = ( - message: DataSourceCallbackMessage -): message is DataSourceDataSizeMessage => - message.type === "viewport-update" && message.mode === "size-only"; - -export interface DataSourceDisabledMessage extends MessageWithClientViewportId { - type: "disabled"; -} - -export interface DataSourceEnabledMessage extends MessageWithClientViewportId { - type: "enabled"; -} - -export interface DataSourceColumnsMessage extends MessageWithClientViewportId { - type: "columns"; - columns: VuuColumns; -} -export interface DataSourceFilterMessage extends MessageWithClientViewportId { - type: "filter"; - filter: DataSourceFilter; -} -export interface DataSourceGroupByMessage extends MessageWithClientViewportId { - type: "groupBy"; - groupBy: VuuGroupBy | undefined; -} -export interface DataSourceSetConfigMessage - extends MessageWithClientViewportId { - type: "config"; - config: WithFullConfig; -} - -export interface DataSourceMenusMessage extends MessageWithClientViewportId { - type: "vuu-menu"; - menu: VuuMenu; -} - -export interface DataSourceSortMessage extends MessageWithClientViewportId { - type: "sort"; - sort: VuuSort; -} - -export type DataSourceConfigMessage = - | DataSourceAggregateMessage - | DataSourceColumnsMessage - | DataSourceFilterMessage - | DataSourceGroupByMessage - | DataSourceSortMessage - | DataSourceSetConfigMessage; - -export const toDataSourceConfig = ( - message: DataSourceConfigMessage -): DataSourceConfig => { - switch (message.type) { - case "aggregate": - return { aggregations: message.aggregations }; - case "columns": - return { columns: message.columns }; - case "filter": - return { filter: message.filter }; - case "groupBy": - return { groupBy: message.groupBy }; - case "sort": - return { sort: message.sort }; - case "config": - return message.config; - } -}; - -const exactlyTheSame = (a: unknown, b: unknown) => { - if (a === b) { - return true; - } else if (a === undefined && b === undefined) { - return true; - } else { - return false; - } -}; - -type DataConfigPredicate = ( - config: DataSourceConfig, - newConfig: DataSourceConfig -) => boolean; - -const equivalentFilter: DataConfigPredicate = ( - { filter: f1 }, - { filter: f2 } -) => - (f1 === undefined && f2?.filter === "") || - (f2 === undefined && f1?.filter === ""); - -export const filterChanged: DataConfigPredicate = (c1, c2) => { - if (equivalentFilter(c1, c2)) { - return false; - } else { - return c1.filter?.filter !== c2.filter?.filter; - } -}; - -const equivalentSort: DataConfigPredicate = ({ sort: s1 }, { sort: s2 }) => - (s1 === undefined && s2?.sortDefs.length === 0) || - (s2 === undefined && s1?.sortDefs.length === 0); - -const sortChanged: DataConfigPredicate = (config, newConfig) => { - const { sort: s1 } = config; - const { sort: s2 } = newConfig; - if (exactlyTheSame(s1, s2) || equivalentSort(config, newConfig)) { - return false; - } else if (s1 === undefined || s2 === undefined) { - return true; - } else if (s1?.sortDefs.length !== s2?.sortDefs.length) { - return true; - } - return s1.sortDefs.some( - ({ column, sortType }, i) => - column !== s2.sortDefs[i].column || sortType !== s2.sortDefs[i].sortType - ); -}; - -export const hasGroupBy = (config?: DataSourceConfig): config is WithGroupBy => - config !== undefined && - config.groupBy !== undefined && - config.groupBy.length > 0; - -export const hasFilter = (config?: DataSourceConfig): config is WithFilter => - config?.filter !== undefined && config.filter.filter.length > 0; - -export const hasSort = (config?: DataSourceConfig): config is WithSort => - config?.sort !== undefined && - Array.isArray(config.sort?.sortDefs) && - config.sort.sortDefs.length > 0; - -const equivalentGroupBy: DataConfigPredicate = ( - { groupBy: val1 }, - { groupBy: val2 } -) => - (val1 === undefined && val2?.length === 0) || - (val2 === undefined && val1?.length === 0); - -export const groupByChanged: DataConfigPredicate = (config, newConfig) => { - const { groupBy: g1 } = config; - const { groupBy: g2 } = newConfig; - if (exactlyTheSame(g1, g2) || equivalentGroupBy(config, newConfig)) { - return false; - } else if (g1 === undefined || g2 === undefined) { - return true; - } else if (g1?.length !== g2?.length) { - return true; - } - return g1.some((column, i) => column !== g2?.[i]); -}; - -const equivalentColumns: DataConfigPredicate = ( - { columns: cols1 }, - { columns: cols2 } -) => - (cols1 === undefined && cols2?.length === 0) || - (cols2 === undefined && cols1?.length === 0); - -export const columnsChanged: DataConfigPredicate = (config, newConfig) => { - const { columns: cols1 } = config; - const { columns: cols2 } = newConfig; - - if (exactlyTheSame(cols1, cols2) || equivalentColumns(config, newConfig)) { - return false; - } else if (cols1 === undefined || cols2 === undefined) { - return true; - } else if (cols1?.length !== cols2?.length) { - return true; - } - return cols1.some((column, i) => column !== cols2?.[i]); -}; - -const equivalentAggregations: DataConfigPredicate = ( - { aggregations: agg1 }, - { aggregations: agg2 } -) => - (agg1 === undefined && agg2?.length === 0) || - (agg2 === undefined && agg1?.length === 0); - -const aggregationsChanged: DataConfigPredicate = (config, newConfig) => { - const { aggregations: agg1 } = config; - const { aggregations: agg2 } = newConfig; - if (exactlyTheSame(agg1, agg2) || equivalentAggregations(config, newConfig)) { - return false; - } else if (agg1 === undefined || agg2 === undefined) { - return true; - } else if (agg1.length !== agg2.length) { - return true; - } - return agg1.some( - ({ column, aggType }, i) => - column !== agg2[i].column || aggType !== agg2[i].aggType - ); -}; -const visualLinkChanged: DataConfigPredicate = () => { - // TODO - return false; -}; - -export const configChanged = ( - config: DataSourceConfig | undefined, - newConfig: DataSourceConfig | undefined -) => { - if (exactlyTheSame(config, newConfig)) { - return false; - } - - if (config === undefined || newConfig === undefined) { - return true; - } - - return ( - columnsChanged(config, newConfig) || - filterChanged(config, newConfig) || - sortChanged(config, newConfig) || - groupByChanged(config, newConfig) || - aggregationsChanged(config, newConfig) || - visualLinkChanged(config, newConfig) - ); -}; - -export interface DataSourceSubscribedMessage - extends MessageWithClientViewportId, - MessageWithClientViewportId { - aggregations: VuuAggregation[]; - columns: VuuColumns; - filter: DataSourceFilter; - groupBy: VuuGroupBy; - range: VuuRange; - sort: VuuSort; - tableSchema: Readonly; - type: "subscribed"; -} - -export interface DataSourceVisualLinkCreatedMessage - extends MessageWithClientViewportId { - colName: string; - parentViewportId: string; - parentColName: string; - type: "vuu-link-created"; -} - -export interface DataSourceVisualLinkRemovedMessage - extends MessageWithClientViewportId { - type: "vuu-link-removed"; -} - -export interface DataSourceVisualLinksMessage - extends MessageWithClientViewportId { - type: "vuu-links"; - links: VuuLinkDescriptor[]; -} - -export type VuuFeatureMessage = - | DataSourceMenusMessage - | DataSourceVisualLinksMessage; - -export type VuuFeatureInvocationMessage = - | DataSourceVisualLinkCreatedMessage - | DataSourceVisualLinkRemovedMessage; - -export type DataSourceCallbackMessage = - | DataSourceConfigMessage - | DataSourceColumnsMessage - | DataSourceDataMessage - | DataSourceDebounceRequest - | DataSourceDisabledMessage - | DataSourceEnabledMessage - | DataSourceMenusMessage - | DataSourceSubscribedMessage - | DataSourceVisualLinkCreatedMessage - | DataSourceVisualLinkRemovedMessage - | DataSourceVisualLinksMessage; - -const datasourceMessages = [ - "config", - "aggregate", - "viewport-update", - "columns", - "debounce-begin", - "disabled", - "enabled", - "filter", - "groupBy", - "vuu-link-created", - "vuu-link-removed", - "vuu-links", - "vuu-menu", - "sort", - "subscribed", -]; - -export type ConfigChangeColumnsMessage = { - type: "columns"; - columns?: ColumnDescriptor[]; -}; - -export type ConfigChangeMessage = - | ConfigChangeColumnsMessage - | DataSourceAggregateMessage - | DataSourceFilterMessage - | DataSourceGroupByMessage - | DataSourceSortMessage - | DataSourceVisualLinkCreatedMessage - | DataSourceVisualLinkRemovedMessage; - -export type ConfigChangeHandler = (msg: ConfigChangeMessage) => void; - -export const shouldMessageBeRoutedToDataSource = ( - message: unknown -): message is DataSourceCallbackMessage => { - const type = (message as DataSourceCallbackMessage).type; - return datasourceMessages.includes(type); -}; - -export const isDataSourceConfigMessage = ( - message: DataSourceCallbackMessage -): message is DataSourceConfigMessage => - ["config", "aggregate", "columns", "filter", "groupBy", "sort"].includes( - message.type - ); - -/** - * Described the configuration values that should typically be - * persisted across sessions. - */ -export interface WithFullConfig { - readonly aggregations: VuuAggregation[]; - readonly columns: string[]; - readonly filter: DataSourceFilter; - readonly groupBy: VuuGroupBy; - readonly sort: VuuSort; - readonly visualLink?: LinkDescriptorWithLabel; -} - -export const NoFilter: VuuFilter = { filter: "" }; -export const NoSort: VuuSort = { sortDefs: [] }; - -export const vanillaConfig: WithFullConfig = { - aggregations: [], - columns: [], - filter: NoFilter, - groupBy: [], - sort: NoSort, -}; - -export const withConfigDefaults = ( - config: DataSourceConfig -): WithFullConfig & { visualLink?: LinkDescriptorWithLabel } => { - if ( - config.aggregations && - config.columns && - config.filter && - config.groupBy && - config.sort - ) { - return config as WithFullConfig; - } else { - const { - aggregations = [], - columns = [], - filter = { filter: "" }, - groupBy = [], - sort = { sortDefs: [] }, - visualLink, - } = config; - - return { - aggregations, - columns, - filter, - groupBy, - sort, - visualLink, - }; - } -}; - -export interface DataSourceConfig extends Partial { - visualLink?: LinkDescriptorWithLabel; -} - -export interface WithGroupBy extends DataSourceConfig { - groupBy: VuuGroupBy; -} -export interface WithFilter extends DataSourceConfig { - filter: DataSourceFilter; -} -export interface WithSort extends DataSourceConfig { - sort: VuuSort; -} - -export interface DataSourceConstructorProps extends DataSourceConfig { - bufferSize?: number; - table: VuuTable; - title?: string; - viewport?: string; -} - -export interface SubscribeProps { - viewport?: string; - columns?: string[]; - aggregations?: VuuAggregation[]; - range?: VuuRange; - sort?: VuuSort; - groupBy?: VuuGroupBy; - filter?: DataSourceFilter; - title?: string; -} - -export type SubscribeCallback = (message: DataSourceCallbackMessage) => void; -export type OptimizeStrategy = "none" | "throttle" | "debounce"; - -export type DataSourceEvents = { - config: (config: DataSourceConfig | undefined, confirmed?: boolean) => void; - optimize: (optimize: OptimizeStrategy) => void; - range: (range: VuuRange) => void; - resize: (size: number) => void; -}; - -/** - * return Promise indicates success - * return Promise indicates failure - */ -export type DataSourceEditHandler = ( - row: DataSourceRow, - columnName: string, - value: VuuRowDataItemType -) => Promise; - -export type DataSourceDeleteHandler = (key: string) => Promise; -export type DataSourceInsertHandler = ( - key: string, - data: VuuDataRowDto -) => Promise; - -export type RpcResponse = - | MenuRpcResponse - | VuuUIMessageInRPCEditReject - | VuuUIMessageInRPCEditResponse - | ViewportRpcResponse; - -export type RpcResponseHandler = (response: RpcResponse) => boolean; - -export type RowSearchPredicate = (row: DataSourceRow) => boolean; - -export type DataSourceStatus = - | "disabled" - | "disabling" - | "enabled" - | "enabling" - | "initialising" - | "subscribing" - | "subscribed" - | "suspended" - | "unsubscribed"; - -export interface TypeaheadSuggestionProvider { - getTypeaheadSuggestions: ( - columnName: string, - pattern?: string - ) => Promise; -} - -export const isTypeaheadSuggestionProvider = ( - source: unknown -): source is TypeaheadSuggestionProvider => - typeof (source as TypeaheadSuggestionProvider)["getTypeaheadSuggestions"] === - "function"; - -export interface DataSource - extends EventEmitter, - Partial { - aggregations: VuuAggregation[]; - applyEdit: DataSourceEditHandler; - /** - * set config without triggering config event. Use this method when initialising - * a dataSource that has been restored from session state. The dataSource will - * not yet be subscribed. Triggering the config event is unnecessary and might - * cause a React exception if the event were to cause a render. - * @param config DataSourceConfig - * @returns true if config has been applied (will not be if existig config is same) - */ - applyConfig: (config: DataSourceConfig) => true | undefined; - closeTreeNode: (key: string, cascade?: boolean) => void; - columns: string[]; - config: DataSourceConfig; - status: DataSourceStatus; - /** - * - * Similar to disable but intended for pauses of very short duration (default is 3 seconds). Although - * the dataSource will stop sending messages until resumed, it will not disconnect from a remote server. - * It will preserve subscription to the remote server and continue to apply updates to cached data. It - * just won't send updates through to the UI thread (until resumed). Useful in edge cases such as where a - * component is dragged to a new location. When dropped, the component will be unmounted and very quickly - * remounted by React. For the duration of this operation, we suspend updates . Updating an unmounted - * React component would cause a React error. - * If an suspend is requested and not resumed within 3 seconds, it will automatically be promoted to a disable., - */ - suspend?: () => void; - resume?: () => void; - - deleteRow?: DataSourceDeleteHandler; - - /** - * For a dataSource that has been previously disabled and is currently in disabled state , this will restore - * the subscription to active status. Fresh data will be dispatched to client. The enable call optionally - * accepts the same subscribe callback as subscribe. This allows a completely new instance of a component to - * assume ownership of a subscription and receive all messages. - */ - enable?: (callback?: SubscribeCallback) => void; - /** - * Disables this subscription. A datasource will send no further messages until re-enabled. Example usage - * might be for a component displayed within a set of Tabs. If user switches to another tab, the dataSource - * of the component that is no longer visible can be disabled until it is made visible again. - */ - disable?: () => void; - filter: DataSourceFilter; - groupBy: VuuGroupBy; - insertRow?: DataSourceInsertHandler; - links?: LinkDescriptorWithLabel[]; - menu?: VuuMenu; - menuRpcCall: ( - rpcRequest: Omit | ClientToServerEditRpc - ) => Promise; - rpcCall?: ( - message: Omit - ) => Promise; - openTreeNode: (key: string) => void; - range: VuuRange; - select: SelectionChangeHandler; - readonly selectedRowsCount: number; - readonly size: number; - sort: VuuSort; - subscribe: ( - props: SubscribeProps, - callback: SubscribeCallback - ) => Promise; - table?: VuuTable; - readonly tableSchema?: TableSchema; - title?: string; - unsubscribe: () => void; - viewport?: string; - visualLink?: LinkDescriptorWithLabel; -} diff --git a/vuu-ui/packages/vuu-data/src/inlined-worker.js b/vuu-ui/packages/vuu-data/src/inlined-worker.js deleted file mode 100644 index 3d014b01e..000000000 --- a/vuu-ui/packages/vuu-data/src/inlined-worker.js +++ /dev/null @@ -1,8 +0,0 @@ -export const workerSourceCode = ` -var de=(s,e,t)=>{if(!e.has(s))throw TypeError("Cannot "+t)};var d=(s,e,t)=>(de(s,e,"read from private field"),t?t.call(s):e.get(s)),k=(s,e,t)=>{if(e.has(s))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(s):e.set(s,t)},ge=(s,e,t,n)=>(de(s,e,"write to private field"),n?n.call(s,t):e.set(s,t),t);function fe(s,e,t=[],n=[]){for(let r=0,o=s.length;r{var e,t;if(((e=globalThis.document)==null?void 0:e.cookie)!==void 0)return(t=globalThis.document.cookie.split("; ").find(n=>n.startsWith(\`\${s}=\`)))==null?void 0:t.split("=")[1]};function K({from:s,to:e},t=0,n=Number.MAX_SAFE_INTEGER){if(t===0)return ns>=e&&s=this.to||ts.replaceAll("/",".")},"dd/mm/yyyy":{locale:"en-GB",options:{...I}},"dd MMM yyyy":{locale:"en-GB",options:{...I,month:"short"}},"dd MMMM yyyy":{locale:"en-GB",options:{...I,month:"long"}},"mm/dd/yyyy":{locale:"en-US",options:{...I}},"MMM dd, yyyy":{locale:"en-US",options:{...I,month:"short"}},"MMMM dd, yyyy":{locale:"en-US",options:{...I,month:"long"}}},Rn={...ut,...at};var ct=["error","warn","info","debug"],pt=s=>typeof s=="string"&&ct.includes(s),dt="error",A=()=>{},gt="error",{loggingLevel:U=gt}=ft(),w=s=>{let e=U==="debug",t=e||U==="info",n=t||U==="warn",r=n||U==="error",o=t?p=>console.info(\`[\${s}] \${p}\`):A,i=n?p=>console.warn(\`[\${s}] \${p}\`):A,u=e?p=>console.debug(\`[\${s}] \${p}\`):A;return{errorEnabled:r,error:r?p=>console.error(\`[\${s}] \${p}\`):A}};function ft(){return typeof loggingSettings<"u"?loggingSettings:{loggingLevel:mt()}}function mt(){let s=me("vuu-logging-level");return pt(s)?s:dt}var{debug:ht,debugEnabled:Ct}=w("range-monitor"),F=class{constructor(e){this.source=e;this.range={from:0,to:0};this.timestamp=0}isSet(){return this.timestamp!==0}set({from:e,to:t}){let{timestamp:n}=this;if(this.range.from=e,this.range.to=t,this.timestamp=performance.now(),n)Ct&&ht(\`<\${this.source}> [\${e}-\${t}], \${(this.timestamp-n).toFixed(0)} ms elapsed\`);else return 0}};function be(s){return Array.isArray(s)}function bt(s){return!Array.isArray(s)}var R,Re=class{constructor(){k(this,R,new Map)}addListener(e,t){let n=d(this,R).get(e);n?be(n)?n.push(t):bt(n)&&d(this,R).set(e,[n,t]):d(this,R).set(e,t)}removeListener(e,t){if(!d(this,R).has(e))return;let n=d(this,R).get(e),r=-1;if(n===t)d(this,R).delete(e);else if(Array.isArray(n)){for(let o=length;o-- >0;)if(n[o]===t){r=o;break}if(r<0)return;n.length===1?(n.length=0,d(this,R).delete(e)):n.splice(r,1)}}removeAllListeners(e){e&&d(this,R).has(e)?d(this,R).delete(e):e===void 0&&d(this,R).clear()}emit(e,...t){if(d(this,R)){let n=d(this,R).get(e);n&&this.invokeHandler(n,t)}}once(e,t){let n=(...r)=>{this.removeListener(e,n),t(...r)};this.on(e,n)}on(e,t){this.addListener(e,t)}hasListener(e,t){let n=d(this,R).get(e);return Array.isArray(n)?n.includes(t):n===t}invokeHandler(e,t){if(be(e))e.slice().forEach(n=>this.invokeHandler(n,t));else switch(t.length){case 0:e();break;case 1:e(t[0]);break;case 2:e(t[0],t[1]);break;default:e.call(null,...t)}}};R=new WeakMap;var N=String.fromCharCode(8200),f=String.fromCharCode(8199);var Ln={DIGIT:f,TWO_DIGITS:f+f,THREE_DIGITS:f+f+f,FULL_PADDING:[null,N+f,N+f+f,N+f+f+f,N+f+f+f+f]};var _n=f+f+f+f+f+f+f+f+f;var{COUNT:rr}=V;var W=class{constructor(e){this.keys=new Map,this.free=[],this.nextKeyValue=0,this.reset(e)}next(){return this.free.length>0?this.free.pop():this.nextKeyValue++}reset({from:e,to:t}){this.keys.forEach((r,o)=>{(o=t)&&(this.free.push(r),this.keys.delete(o))});let n=t-e;this.keys.size+this.free.length>n&&(this.free.length=Math.max(0,n-this.keys.size));for(let r=e;rthis.keys.size&&(this.nextKeyValue=this.keys.size)}keyFor(e){let t=this.keys.get(e);if(t===void 0)throw console.log(\`key not found - keys: \${this.toDebugString()} - free : \${this.free.join(",")} - \`),Error(\`KeySet, no key found for rowIndex \${e}\`);return t}toDebugString(){return Array.from(this.keys.entries()).map((e,t)=>\`\${e}=>\${t}\`).join(",")}};var{IDX:pr}=V;var{SELECTED:fr}=V,M={False:0,True:1,First:2,Last:4};var Rt=(s,e)=>e>=s[0]&&e<=s[1],Tt=M.True+M.First+M.Last,yt=M.True+M.First,St=M.True+M.Last,Q=(s,e)=>{for(let t of s)if(typeof t=="number"){if(t===e)return Tt}else if(Rt(t,e))return e===t[0]?yt:e===t[1]?St:M.True;return M.False};var Te=s=>{if(s.every(t=>typeof t=="number"))return s;let e=[];for(let t of s)if(typeof t=="number")e.push(t);else for(let n=t[0];n<=t[1];n++)e.push(n);return e};var wt=(()=>{let s=0,e=()=>\`0000\${(Math.random()*36**4<<0).toString(36)}\`.slice(-4);return()=>(s+=1,\`u\${e()}\${s}\`)})();var{debug:Ks,debugEnabled:Qs,error:we,info:E,infoEnabled:vt,warn:P}=w("websocket-connection"),Ee="ws",It=s=>s.startsWith(Ee+"://")||s.startsWith(Ee+"s://"),xe={},Z=Symbol("setWebsocket"),q=Symbol("connectionCallback");async function ve(s,e,t,n=10,r=5){return xe[s]={status:"connecting",connect:{allowed:r,remaining:r},reconnect:{allowed:n,remaining:n}},Ie(s,e,t)}async function Y(s){throw Error("connection broken")}async function Ie(s,e,t,n){let{status:r,connect:o,reconnect:i}=xe[s],u=r==="connecting"?o:i;try{t({type:"connection-status",status:"connecting"});let c=typeof n<"u",p=await Pt(s,e);console.info("%c\u26A1 %cconnected","font-size: 24px;color: green;font-weight: bold;","color:green; font-size: 14px;"),n!==void 0&&n[Z](p);let a=n!=null?n:new ee(p,s,e,t),l=c?"reconnected":"connection-open-awaiting-session";return t({type:"connection-status",status:l}),a.status=l,u.remaining=u.allowed,a}catch{let p=--u.remaining>0;if(t({type:"connection-status",status:"disconnected",reason:"failed to connect",retry:p}),p)return Dt(s,e,t,n,2e3);throw Error("Failed to establish connection")}}var Dt=(s,e,t,n,r)=>new Promise(o=>{setTimeout(()=>{o(Ie(s,e,t,n))},r)}),Pt=(s,e)=>new Promise((t,n)=>{let r=It(s)?s:\`wss://\${s}\`;vt&&e!==void 0&&E(\`WebSocket Protocol \${e==null?void 0:e.toString()}\`);let o=new WebSocket(r,e);o.onopen=()=>t(o),o.onerror=i=>n(i)}),Ve=()=>{P==null||P("Connection cannot be closed, socket not yet opened")},Me=s=>{P==null||P(\`Message cannot be sent, socket closed \${s.body.type}\`)},Lt=s=>{try{return JSON.parse(s)}catch{throw Error(\`Error parsing JSON response from server \${s}\`)}},ee=class{constructor(e,t,n,r){this.close=Ve;this.requiresLogin=!0;this.send=Me;this.status="ready";this.messagesCount=0;this.connectionMetricsInterval=null;this.handleWebsocketMessage=e=>{let t=Lt(e.data);this.messagesCount+=1,this[q](t)};this.url=t,this.protocol=n,this[q]=r,this[Z](e)}reconnect(){Y(this)}[(q,Z)](e){let t=this[q];e.onmessage=o=>{this.status="connected",e.onmessage=this.handleWebsocketMessage,this.handleWebsocketMessage(o)},this.connectionMetricsInterval=setInterval(()=>{t({type:"connection-metrics",messagesLength:this.messagesCount}),this.messagesCount=0},2e3),e.onerror=()=>{we("\u26A1 connection error"),t({type:"connection-status",status:"disconnected",reason:"error"}),this.connectionMetricsInterval&&(clearInterval(this.connectionMetricsInterval),this.connectionMetricsInterval=null),this.status==="connection-open-awaiting-session"?we("Websocket connection lost before Vuu session established, check websocket configuration"):this.status!=="closed"&&(Y(this),this.send=r)},e.onclose=()=>{E==null||E("\u26A1 connection close"),t({type:"connection-status",status:"disconnected",reason:"close"}),this.connectionMetricsInterval&&(clearInterval(this.connectionMetricsInterval),this.connectionMetricsInterval=null),this.status!=="closed"&&(Y(this),this.send=r)};let n=o=>{e.send(JSON.stringify(o))},r=o=>{E==null||E(\`TODO queue message until websocket reconnected \${o.body.type}\`)};this.send=n,this.close=()=>{this.status="closed",e.close(),this.close=Ve,this.send=Me,E==null||E("close websocket")}}};var _t=["VIEW_PORT_MENUS_SELECT_RPC","VIEW_PORT_MENU_TABLE_RPC","VIEW_PORT_MENU_ROW_RPC","VIEW_PORT_MENU_CELL_RPC","VP_EDIT_CELL_RPC","VP_EDIT_ROW_RPC","VP_EDIT_ADD_ROW_RPC","VP_EDIT_DELETE_CELL_RPC","VP_EDIT_DELETE_ROW_RPC","VP_EDIT_SUBMIT_FORM_RPC"],De=s=>_t.includes(s.type),Pe=s=>s.type==="VIEW_PORT_RPC_CALL",\$=({requestId:s,...e})=>[s,e],Le=s=>{let e=s.at(0);if(e.updateType==="SIZE"){if(s.length===1)return s;e=s.at(1)}let t=s.at(-1);return[e,t]},_e=s=>{let e={};for(let t of s)(e[t.viewPortId]||(e[t.viewPortId]=[])).push(t);return e};var te=({columns:s,dataTypes:e,key:t,table:n})=>({table:n,columns:s.map((r,o)=>({name:r,serverDataType:e[o]})),key:t});var Oe=s=>s.type==="connection-status",ke=s=>s.type==="connection-metrics";var Ae=s=>"viewport"in s,Ue=s=>s.type==="VIEW_PORT_MENU_RESP"&&s.action!==null&&G(s.action.table),G=s=>s!==null&&typeof s=="object"&&"table"in s&&"module"in s?s.table.startsWith("session"):!1;var Fe="CHANGE_VP_SUCCESS";var Ne="CLOSE_TREE_NODE",We="CLOSE_TREE_SUCCESS";var qe="CREATE_VP",\$e="DISABLE_VP",Ge="DISABLE_VP_SUCCESS";var Be="ENABLE_VP",He="ENABLE_VP_SUCCESS";var ne="GET_VP_VISUAL_LINKS",je="GET_VIEW_PORT_MENUS";var ze="HB",Je="HB_RESP",Ke="LOGIN",Qe="OPEN_TREE_NODE",Xe="OPEN_TREE_SUCCESS";var Ye="REMOVE_VP";var Ze="SET_SELECTION_SUCCESS";var tt=s=>{switch(s){case"TypeAheadRpcHandler":return"TYPEAHEAD";default:return"SIMUL"}};var nt=[],T=w("array-backed-moving-window");function Ot(s,e){if(!e||e.data.length!==s.data.length||e.sel!==s.sel)return!1;for(let t=0;t{var t;if((t=T.info)==null||t.call(T,\`setRowCount \${e}\`),e{let n=this.bufferSize*.25;return d(this,h).to-t0&&e-d(this,h).from0&&this.clientRange.from+this.rowsWithinRange===this.rowCount}outOfRange(e,t){let{from:n,to:r}=this.range;if(t=r)return!0}setAtIndex(e){let{rowIndex:t}=e,n=t-d(this,h).from;if(Ot(e,this.internalData[n]))return!1;let r=this.isWithinClientRange(t);return(r||this.isWithinRange(t))&&(!this.internalData[n]&&r&&(this.rowsWithinRange+=1),this.internalData[n]=e),r}getAtIndex(e){return d(this,h).isWithin(e)&&this.internalData[e-d(this,h).from]!=null?this.internalData[e-d(this,h).from]:void 0}isWithinRange(e){return d(this,h).isWithin(e)}isWithinClientRange(e){return this.clientRange.isWithin(e)}setClientRange(e,t){var p;(p=T.debug)==null||p.call(T,\`setClientRange \${e} - \${t}\`);let n=this.clientRange.from,r=Math.min(this.clientRange.to,this.rowCount);if(e===n&&t===r)return[!1,nt];let o=this.clientRange.copy();this.clientRange.from=e,this.clientRange.to=t,this.rowsWithinRange=0;for(let a=e;ao.to){let a=Math.max(e,o.to);i=this.internalData.slice(a-u,t-u)}else{let a=Math.min(o.from,t);i=this.internalData.slice(e-u,a-u)}return[this.bufferBreakout(e,t),i]}setRange(e,t){var n,r;if(e!==d(this,h).from||t!==d(this,h).to){(n=T.debug)==null||n.call(T,\`setRange \${e} - \${t}\`);let[o,i]=d(this,h).overlap(e,t),u=new Array(t-e);this.rowsWithinRange=0;for(let c=o;c=0;o--)if(e[o]!==void 0){r=e[o];break}return n&&r?[n.rowIndex,r.rowIndex]:[-1,-1]}};h=new WeakMap;var kt=[],{debug:C,debugEnabled:H,error:At,info:g,infoEnabled:Ut,warn:L}=w("viewport"),Ft=({rowKey:s,updateType:e})=>e==="U"&&!s.startsWith("\$root"),j=[void 0,void 0],Nt={count:0,mode:void 0,size:0,ts:0},z=class{constructor({aggregations:e,bufferSize:t=50,columns:n,filter:r,groupBy:o=[],table:i,range:u,sort:c,title:p,viewport:a,visualLink:l},m){this.batchMode=!0;this.hasUpdates=!1;this.pendingUpdates=[];this.pendingOperations=new Map;this.pendingRangeRequests=[];this.rowCountChanged=!1;this.selectedRows=[];this.useBatchMode=!0;this.lastUpdateStatus=Nt;this.updateThrottleTimer=void 0;this.rangeMonitor=new F("ViewPort");this.disabled=!1;this.isTree=!1;this.status="";this.suspended=!1;this.suspendTimer=null;this.setLastSizeOnlyUpdateSize=e=>{this.lastUpdateStatus.size=e};this.setLastUpdate=e=>{let{ts:t,mode:n}=this.lastUpdateStatus,r=0;if(n===e){let o=Date.now();this.lastUpdateStatus.count+=1,this.lastUpdateStatus.ts=o,r=t===0?0:o-t}else this.lastUpdateStatus.count=1,this.lastUpdateStatus.ts=0,r=0;return this.lastUpdateStatus.mode=e,r};this.rangeRequestAlreadyPending=e=>{let{bufferSize:t}=this,n=t*.25,{from:r}=e;for(let{from:o,to:i}of this.pendingRangeRequests)if(r>=o&&r{this.updateThrottleTimer=void 0,this.lastUpdateStatus.count=3,this.postMessageToClient({clientViewportId:this.clientViewportId,mode:"size-only",size:this.lastUpdateStatus.size,type:"viewport-update"})};this.shouldThrottleMessage=e=>{let t=this.setLastUpdate(e);return e==="size-only"&&t>0&&t<500&&this.lastUpdateStatus.count>3};this.throttleMessage=e=>this.shouldThrottleMessage(e)?(g==null||g("throttling updates setTimeout to 2000"),this.updateThrottleTimer===void 0&&(this.updateThrottleTimer=setTimeout(this.sendThrottledSizeMessage,2e3)),!0):(this.updateThrottleTimer!==void 0&&(clearTimeout(this.updateThrottleTimer),this.updateThrottleTimer=void 0),!1);this.getNewRowCount=()=>{if(this.rowCountChanged&&this.dataWindow)return this.rowCountChanged=!1,this.dataWindow.rowCount};this.aggregations=e,this.bufferSize=t,this.clientRange=u,this.clientViewportId=a,this.columns=n,this.filter=r,this.groupBy=o,this.keys=new W(u),this.pendingLinkedParent=l,this.table=i,this.sort=c,this.title=p,Ut&&(g==null||g(\`constructor #\${a} \${i.table} bufferSize=\${t}\`)),this.dataWindow=new B(this.clientRange,u,this.bufferSize),this.postMessageToClient=m}get hasUpdatesToProcess(){return this.suspended?!1:this.rowCountChanged||this.hasUpdates}get size(){var e;return(e=this.dataWindow.rowCount)!=null?e:0}subscribe(){let{filter:e}=this.filter;return this.status=this.status==="subscribed"?"resubscribing":"subscribing",{type:qe,table:this.table,range:K(this.clientRange,this.bufferSize),aggregations:this.aggregations,columns:this.columns,sort:this.sort,groupBy:this.groupBy,filterSpec:{filter:e}}}handleSubscribed({viewPortId:e,aggregations:t,columns:n,filterSpec:r,range:o,sort:i,groupBy:u},c){return this.serverViewportId=e,this.status="subscribed",this.aggregations=t,this.columns=n,this.groupBy=u,this.isTree=u&&u.length>0,this.dataWindow.setRange(o.from,o.to),{aggregations:t,type:"subscribed",clientViewportId:this.clientViewportId,columns:n,filter:r,groupBy:u,range:o,sort:i,tableSchema:c}}awaitOperation(e,t){this.pendingOperations.set(e,t)}completeOperation(e,...t){var u;let{clientViewportId:n,pendingOperations:r}=this,o=r.get(e);if(!o){At(\`no matching operation found to complete for requestId \${e}\`);return}let{type:i}=o;if(g==null||g(\`completeOperation \${i}\`),r.delete(e),i==="CHANGE_VP_RANGE"){let[c,p]=t;(u=this.dataWindow)==null||u.setRange(c,p);for(let a=this.pendingRangeRequests.length-1;a>=0;a--){let l=this.pendingRangeRequests[a];if(l.requestId===e){l.acked=!0;break}else L==null||L("range requests sent faster than they are being ACKed")}}else if(i==="config"){let{aggregations:c,columns:p,filter:a,groupBy:l,sort:m}=o.data;return this.aggregations=c,this.columns=p,this.filter=a,this.groupBy=l,this.sort=m,l.length>0?this.isTree=!0:this.isTree&&(this.isTree=!1),C==null||C(\`config change confirmed, isTree : \${this.isTree}\`),{clientViewportId:n,type:i,config:o.data}}else{if(i==="groupBy")return this.isTree=o.data.length>0,this.groupBy=o.data,C==null||C(\`groupBy change confirmed, isTree : \${this.isTree}\`),{clientViewportId:n,type:i,groupBy:o.data};if(i==="columns")return this.columns=o.data,{clientViewportId:n,type:i,columns:o.data};if(i==="filter")return this.filter=o.data,{clientViewportId:n,type:i,filter:o.data};if(i==="aggregate")return this.aggregations=o.data,{clientViewportId:n,type:"aggregate",aggregations:this.aggregations};if(i==="sort")return this.sort=o.data,{clientViewportId:n,type:i,sort:this.sort};if(i!=="selection"){if(i==="disable")return this.disabled=!0,{type:"disabled",clientViewportId:n};if(i==="enable")return this.disabled=!1,{type:"enabled",clientViewportId:n};if(i==="CREATE_VISUAL_LINK"){let[c,p,a]=t;return this.linkedParent={colName:c,parentViewportId:p,parentColName:a},this.pendingLinkedParent=void 0,{type:"vuu-link-created",clientViewportId:n,colName:c,parentViewportId:p,parentColName:a}}else if(i==="REMOVE_VISUAL_LINK")return this.linkedParent=void 0,{type:"vuu-link-removed",clientViewportId:n}}}}rangeRequest(e,t){H&&this.rangeMonitor.set(t);let n="CHANGE_VP_RANGE";if(this.dataWindow){let[r,o]=this.dataWindow.setClientRange(t.from,t.to),i,u=this.dataWindow.rowCount||void 0,c=r&&!this.rangeRequestAlreadyPending(t)?{type:n,viewPortId:this.serverViewportId,...K(t,this.bufferSize,u)}:null;if(c){H&&(C==null||C(\`create CHANGE_VP_RANGE: [\${c.from} - \${c.to}]\`)),this.awaitOperation(e,{type:n});let a=this.pendingRangeRequests.at(-1);if(a)if(a.acked)console.warn("Range Request before previous request is filled");else{let{from:l,to:m}=a;this.dataWindow.outOfRange(l,m)?i={clientViewportId:this.clientViewportId,type:"debounce-begin"}:L==null||L("Range Request before previous request is acked")}this.pendingRangeRequests.push({...c,requestId:e}),this.useBatchMode&&(this.batchMode=!0)}else o.length>0&&(this.batchMode=!1);this.keys.reset(this.dataWindow.clientRange);let p=this.isTree?se:re;return o.length?[c,o.map(a=>p(a,this.keys,this.selectedRows))]:i?[c,void 0,i]:[c]}else return[null]}setLinks(e){return this.links=e,[{type:"vuu-links",links:e,clientViewportId:this.clientViewportId},this.pendingLinkedParent]}setMenu(e){return{type:"vuu-menu",menu:e,clientViewportId:this.clientViewportId}}openTreeNode(e,t){return this.useBatchMode&&(this.batchMode=!0),{type:Qe,vpId:this.serverViewportId,treeKey:t.key}}closeTreeNode(e,t){return this.useBatchMode&&(this.batchMode=!0),{type:Ne,vpId:this.serverViewportId,treeKey:t.key}}createLink(e,t,n,r){let o={type:"CREATE_VISUAL_LINK",parentVpId:n,childVpId:this.serverViewportId,parentColumnName:r,childColumnName:t};return this.awaitOperation(e,o),this.useBatchMode&&(this.batchMode=!0),o}removeLink(e){let t={type:"REMOVE_VISUAL_LINK",childVpId:this.serverViewportId};return this.awaitOperation(e,t),t}suspend(){this.suspended=!0,g==null||g("suspend")}resume(){return this.suspended=!1,H&&(C==null||C(\`resume: \${this.currentData()}\`)),[this.size,this.currentData()]}currentData(){let e=[];if(this.dataWindow){let t=this.dataWindow.getData(),{keys:n}=this,r=this.isTree?se:re;for(let o of t)o&&e.push(r(o,n,this.selectedRows))}return e}enable(e){return this.awaitOperation(e,{type:"enable"}),g==null||g(\`enable: \${this.serverViewportId}\`),{type:Be,viewPortId:this.serverViewportId}}disable(e){return this.awaitOperation(e,{type:"disable"}),g==null||g(\`disable: \${this.serverViewportId}\`),this.suspended=!1,{type:\$e,viewPortId:this.serverViewportId}}columnRequest(e,t){return this.awaitOperation(e,{type:"columns",data:t}),C==null||C(\`columnRequest: \${t}\`),this.createRequest({columns:t})}filterRequest(e,t){this.awaitOperation(e,{type:"filter",data:t}),this.useBatchMode&&(this.batchMode=!0);let{filter:n}=t;return g==null||g(\`filterRequest: \${n}\`),this.createRequest({filterSpec:{filter:n}})}setConfig(e,t){this.awaitOperation(e,{type:"config",data:t});let{filter:n,...r}=t;return this.useBatchMode&&(this.batchMode=!0),H?C==null||C(\`setConfig \${JSON.stringify(t)}\`):g==null||g("setConfig"),this.createRequest({...r,filterSpec:typeof(n==null?void 0:n.filter)=="string"?{filter:n.filter}:{filter:""}},!0)}aggregateRequest(e,t){return this.awaitOperation(e,{type:"aggregate",data:t}),g==null||g(\`aggregateRequest: \${t}\`),this.createRequest({aggregations:t})}sortRequest(e,t){return this.awaitOperation(e,{type:"sort",data:t}),g==null||g(\`sortRequest: \${JSON.stringify(t.sortDefs)}\`),this.createRequest({sort:t})}groupByRequest(e,t=kt){var n;return this.awaitOperation(e,{type:"groupBy",data:t}),this.useBatchMode&&(this.batchMode=!0),this.isTree||(n=this.dataWindow)==null||n.clear(),this.createRequest({groupBy:t})}selectRequest(e,t){return this.selectedRows=t,this.awaitOperation(e,{type:"selection",data:t}),g==null||g(\`selectRequest: \${t}\`),{type:"SET_SELECTION",vpId:this.serverViewportId,selection:Te(t)}}removePendingRangeRequest(e,t){for(let n=this.pendingRangeRequests.length-1;n>=0;n--){let{from:r,to:o}=this.pendingRangeRequests[n],i=!0;if(e>=r&&er&&t0){e=[],t="update";for(let i of this.pendingUpdates)e.push(o(i,n,r));this.pendingUpdates.length=0}else{let i=this.dataWindow.getData();if(this.dataWindow.hasAllRowsWithinRange){e=[],t="batch";for(let u of i)e.push(o(u,n,r));this.batchMode=!1}}this.hasUpdates=!1}return this.throttleMessage(t)?j:[e,t]}createRequest(e,t=!1){return t?{type:"CHANGE_VP",viewPortId:this.serverViewportId,...e}:{type:"CHANGE_VP",viewPortId:this.serverViewportId,aggregations:this.aggregations,columns:this.columns,sort:this.sort,groupBy:this.groupBy,filterSpec:{filter:this.filter.filter},...e}}},re=({rowIndex:s,rowKey:e,sel:t,data:n},r,o)=>[s,r.keyFor(s),!0,!1,0,0,e,t?Q(o,s):0].concat(n),se=({rowIndex:s,rowKey:e,sel:t,data:n},r,o)=>{let[i,u,,c,,p,...a]=n;return[s,r.keyFor(s),c,u,i,p,e,t?Q(o,s):0].concat(a)};var rt=1;var{debug:x,debugEnabled:oe,error:_,info:S,infoEnabled:Wt,warn:ie}=w("server-proxy"),b=()=>\`\${rt++}\`,qt={},\$t=s=>s.disabled!==!0&&s.suspended!==!0,Gt={type:"NO_ACTION"},Bt=(s,e,t)=>s.map(n=>n.parentVpId===e?{...n,label:t}:n);function Ht(s,e){return s.map(t=>{let{parentVpId:n}=t,r=e.get(n);if(r)return{...t,parentClientVpId:r.clientViewportId,label:r.title};throw Error("addLabelsToLinks viewport not found")})}var J=class{constructor(e,t){this.authToken="";this.user="user";this.pendingRequests=new Map;this.queuedRequests=[];this.cachedTableMetaRequests=new Map;this.cachedTableSchemas=new Map;this.connection=e,this.postMessageToClient=t,this.viewports=new Map,this.mapClientToServerViewport=new Map}async reconnect(){await this.login(this.authToken);let[e,t]=fe(Array.from(this.viewports.values()),\$t);this.viewports.clear(),this.mapClientToServerViewport.clear();let n=r=>{r.forEach(o=>{let{clientViewportId:i}=o;this.viewports.set(i,o),this.sendMessageToServer(o.subscribe(),i)})};n(e),setTimeout(()=>{n(t)},2e3)}async login(e,t="user"){if(e)return this.authToken=e,this.user=t,new Promise((n,r)=>{this.sendMessageToServer({type:Ke,token:this.authToken,user:t},""),this.pendingLogin={resolve:n,reject:r}});this.authToken===""&&_("login, cannot login until auth token has been obtained")}subscribe(e){if(this.mapClientToServerViewport.has(e.viewport))_(\`spurious subscribe call \${e.viewport}\`);else{let t=this.getTableMeta(e.table),n=new z(e,this.postMessageToClient);this.viewports.set(e.viewport,n);let r=this.awaitResponseToMessage(n.subscribe(),e.viewport);Promise.all([r,t]).then(([i,u])=>{let{viewPortId:c}=i,{status:p}=n;e.viewport!==c&&(this.viewports.delete(e.viewport),this.viewports.set(c,n)),this.mapClientToServerViewport.set(e.viewport,c);let a=n.handleSubscribed(i,u);a&&(this.postMessageToClient(a),oe&&x(\`post DataSourceSubscribedMessage to client: \${JSON.stringify(a)}\`)),n.disabled&&this.disableViewport(n),this.queuedRequests.length>0&&this.processQueuedRequests(),p==="subscribing"&&!G(n.table)&&(this.sendMessageToServer({type:ne,vpId:c}),this.sendMessageToServer({type:je,vpId:c}),Array.from(this.viewports.entries()).filter(([l,{disabled:m}])=>l!==c&&!m).forEach(([l])=>{this.sendMessageToServer({type:ne,vpId:l})}))})}}processQueuedRequests(){let e={};for(;this.queuedRequests.length;){let t=this.queuedRequests.pop();if(t){let{clientViewportId:n,message:r,requestId:o}=t;if(r.type==="CHANGE_VP_RANGE"){if(e.CHANGE_VP_RANGE)continue;e.CHANGE_VP_RANGE=!0;let i=this.mapClientToServerViewport.get(n);i&&this.sendMessageToServer({...r,viewPortId:i},o)}}}}unsubscribe(e){let t=this.mapClientToServerViewport.get(e);t?(S==null||S(\`Unsubscribe Message (Client to Server): - \${t}\`),this.sendMessageToServer({type:Ye,viewPortId:t})):_(\`failed to unsubscribe client viewport \${e}, viewport not found\`)}getViewportForClient(e,t=!0){let n=this.mapClientToServerViewport.get(e);if(n){let r=this.viewports.get(n);if(r)return r;if(t)throw Error(\`Viewport not found for client viewport \${e}\`);return null}else{if(this.viewports.has(e))return this.viewports.get(e);if(t)throw Error(\`Viewport server id not found for client viewport \${e}\`);return null}}setViewRange(e,t){let n=b(),[r,o,i]=e.rangeRequest(n,t.range);S==null||S(\`setViewRange \${t.range.from} - \${t.range.to}\`),r&&(this.sendIfReady(r,n,e.status==="subscribed")||this.queuedRequests.push({clientViewportId:t.viewport,message:r,requestId:n})),o?(S==null||S(\`setViewRange \${o.length} rows returned from cache\`),this.postMessageToClient({mode:"batch",type:"viewport-update",clientViewportId:e.clientViewportId,rows:o})):i&&this.postMessageToClient(i)}setConfig(e,t){let n=b(),r=e.setConfig(n,t.config);this.sendIfReady(r,n,e.status==="subscribed")}aggregate(e,t){let n=b(),r=e.aggregateRequest(n,t.aggregations);this.sendIfReady(r,n,e.status==="subscribed")}sort(e,t){let n=b(),r=e.sortRequest(n,t.sort);this.sendIfReady(r,n,e.status==="subscribed")}groupBy(e,t){let n=b(),r=e.groupByRequest(n,t.groupBy);this.sendIfReady(r,n,e.status==="subscribed")}filter(e,t){let n=b(),{filter:r}=t,o=e.filterRequest(n,r);this.sendIfReady(o,n,e.status==="subscribed")}setColumns(e,t){let n=b(),{columns:r}=t,o=e.columnRequest(n,r);this.sendIfReady(o,n,e.status==="subscribed")}setTitle(e,t){e&&(e.title=t.title,this.updateTitleOnVisualLinks(e))}select(e,t){let n=b(),{selected:r}=t,o=e.selectRequest(n,r);this.sendIfReady(o,n,e.status==="subscribed")}disableViewport(e){let t=b(),n=e.disable(t);this.sendIfReady(n,t,e.status==="subscribed")}enableViewport(e){if(e.disabled){let t=b(),n=e.enable(t);this.sendIfReady(n,t,e.status==="subscribed")}}suspendViewport(e){e.suspend(),e.suspendTimer=setTimeout(()=>{S==null||S("suspendTimer expired, escalate suspend to disable"),this.disableViewport(e)},3e3)}resumeViewport(e){e.suspendTimer&&(x==null||x("clear suspend timer"),clearTimeout(e.suspendTimer),e.suspendTimer=null);let[t,n]=e.resume();x==null||x(\`resumeViewport size \${t}, \${n.length} rows sent to client\`),this.postMessageToClient({clientViewportId:e.clientViewportId,mode:"batch",rows:n,size:t,type:"viewport-update"})}openTreeNode(e,t){if(e.serverViewportId){let n=b();this.sendIfReady(e.openTreeNode(n,t),n,e.status==="subscribed")}}closeTreeNode(e,t){if(e.serverViewportId){let n=b();this.sendIfReady(e.closeTreeNode(n,t),n,e.status==="subscribed")}}createLink(e,t){let{parentClientVpId:n,parentColumnName:r,childColumnName:o}=t,i=b(),u=this.mapClientToServerViewport.get(n);if(u){let c=e.createLink(i,o,u,r);this.sendMessageToServer(c,i)}else _("ServerProxy unable to create link, viewport not found")}removeLink(e){let t=b(),n=e.removeLink(t);this.sendMessageToServer(n,t)}updateTitleOnVisualLinks(e){var r;let{serverViewportId:t,title:n}=e;for(let o of this.viewports.values())if(o!==e&&o.links&&t&&n&&(r=o.links)!=null&&r.some(i=>i.parentVpId===t)){let[i]=o.setLinks(Bt(o.links,t,n));this.postMessageToClient(i)}}removeViewportFromVisualLinks(e){var t;for(let n of this.viewports.values())if((t=n.links)!=null&&t.some(({parentVpId:r})=>r===e)){let[r]=n.setLinks(n.links.filter(({parentVpId:o})=>o!==e));this.postMessageToClient(r)}}menuRpcCall(e){let t=this.getViewportForClient(e.vpId,!1);if(t!=null&&t.serverViewportId){let[n,r]=\$(e);this.sendMessageToServer({...r,vpId:t.serverViewportId},n)}}viewportRpcCall(e){let t=this.getViewportForClient(e.vpId,!1);if(t!=null&&t.serverViewportId){let[n,r]=\$(e);this.sendMessageToServer({...r,vpId:t.serverViewportId,namedParams:{}},n)}}rpcCall(e){let[t,n]=\$(e),r=tt(n.service);this.sendMessageToServer(n,t,{module:r})}handleMessageFromClient(e){var t;if(Ae(e))if(e.type==="disable"){let n=this.getViewportForClient(e.viewport,!1);return n!==null?this.disableViewport(n):void 0}else{let n=this.getViewportForClient(e.viewport);switch(e.type){case"setViewRange":return this.setViewRange(n,e);case"config":return this.setConfig(n,e);case"aggregate":return this.aggregate(n,e);case"sort":return this.sort(n,e);case"groupBy":return this.groupBy(n,e);case"filter":return this.filter(n,e);case"select":return this.select(n,e);case"suspend":return this.suspendViewport(n);case"resume":return this.resumeViewport(n);case"enable":return this.enableViewport(n);case"openTreeNode":return this.openTreeNode(n,e);case"closeTreeNode":return this.closeTreeNode(n,e);case"createLink":return this.createLink(n,e);case"removeLink":return this.removeLink(n);case"setColumns":return this.setColumns(n,e);case"setTitle":return this.setTitle(n,e);default:}}else{if(Pe(e))return this.viewportRpcCall(e);if(De(e))return this.menuRpcCall(e);{let{type:n,requestId:r}=e;switch(n){case"GET_TABLE_LIST":{(t=this.tableList)!=null||(this.tableList=this.awaitResponseToMessage({type:n},r)),this.tableList.then(o=>{this.postMessageToClient({type:"TABLE_LIST_RESP",tables:o.tables,requestId:r})});return}case"GET_TABLE_META":{this.getTableMeta(e.table,r).then(o=>{o&&this.postMessageToClient({type:"TABLE_META_RESP",tableSchema:o,requestId:r})});return}case"RPC_CALL":return this.rpcCall(e);default:}}}_(\`Vuu ServerProxy Unexpected message from client \${JSON.stringify(e)}\`)}getTableMeta(e,t=b()){if(G(e))return Promise.resolve(void 0);let n=\`\${e.module}:\${e.table}\`,r=this.cachedTableMetaRequests.get(n);return r||(r=this.awaitResponseToMessage({type:"GET_TABLE_META",table:e},t),this.cachedTableMetaRequests.set(n,r)),r==null?void 0:r.then(o=>this.cacheTableMeta(o))}awaitResponseToMessage(e,t=b()){return new Promise((n,r)=>{this.sendMessageToServer(e,t),this.pendingRequests.set(t,{reject:r,resolve:n})})}sendIfReady(e,t,n=!0){return n&&this.sendMessageToServer(e,t),n}sendMessageToServer(e,t=\`\${rt++}\`,n=qt){let{module:r="CORE"}=n;this.authToken&&this.connection.send({requestId:t,sessionId:this.sessionId,token:this.authToken,user:this.user,module:r,body:e})}handleMessageFromServer(e){var u;let{body:t,requestId:n,sessionId:r}=e,o=this.pendingRequests.get(n);if(o){let{resolve:a}=o;this.pendingRequests.delete(n),a(t);return}let{viewports:i}=this;switch(t.type){case ze:this.sendMessageToServer({type:Je,ts:+new Date},"NA");break;case"LOGIN_SUCCESS":if(r)this.sessionId=r,(u=this.pendingLogin)==null||u.resolve(r),this.pendingLogin=void 0;else throw Error("LOGIN_SUCCESS did not provide sessionId");break;case"REMOVE_VP_SUCCESS":{let a=i.get(t.viewPortId);a&&(this.mapClientToServerViewport.delete(a.clientViewportId),i.delete(t.viewPortId),this.removeViewportFromVisualLinks(t.viewPortId))}break;case Ze:{let a=this.viewports.get(t.vpId);a&&a.completeOperation(n)}break;case Fe:case Ge:if(i.has(t.viewPortId)){let a=this.viewports.get(t.viewPortId);if(a){let l=a.completeOperation(n);l!==void 0&&(this.postMessageToClient(l),oe&&x(\`postMessageToClient \${JSON.stringify(l)}\`))}}break;case He:{let a=this.viewports.get(t.viewPortId);if(a){let l=a.completeOperation(n);if(l){this.postMessageToClient(l);let[m,y]=a.resume();this.postMessageToClient({clientViewportId:a.clientViewportId,mode:"batch",rows:y,size:m,type:"viewport-update"})}}}break;case"TABLE_ROW":{let a=_e(t.rows);for(let[l,m]of Object.entries(a)){let y=i.get(l);y?y.updateRows(m):ie==null||ie(\`TABLE_ROW message received for non registered viewport \${l}\`)}this.processUpdates()}break;case"CHANGE_VP_RANGE_SUCCESS":{let a=this.viewports.get(t.viewPortId);if(a){let{from:l,to:m}=t;a.completeOperation(n,l,m)}}break;case Xe:case We:break;case"CREATE_VISUAL_LINK_SUCCESS":{let a=this.viewports.get(t.childVpId),l=this.viewports.get(t.parentVpId);if(a&&l){let{childColumnName:m,parentColumnName:y}=t,O=a.completeOperation(n,m,l.clientViewportId,y);O&&this.postMessageToClient(O)}}break;case"REMOVE_VISUAL_LINK_SUCCESS":{let a=this.viewports.get(t.childVpId);if(a){let l=a.completeOperation(n);l&&this.postMessageToClient(l)}}break;case"VP_VISUAL_LINKS_RESP":{let a=this.getActiveLinks(t.links),l=this.viewports.get(t.vpId);if(a.length&&l){let m=Ht(a,this.viewports),[y,O]=l.setLinks(m);if(this.postMessageToClient(y),O){let{link:le,parentClientVpId:st}=O,ce=b(),pe=this.mapClientToServerViewport.get(st);if(pe){let ot=l.createLink(ce,le.fromColumn,pe,le.toColumn);this.sendMessageToServer(ot,ce)}}}}break;case"VIEW_PORT_MENUS_RESP":if(t.menu.name){let a=this.viewports.get(t.vpId);if(a){let l=a.setMenu(t.menu);this.postMessageToClient(l)}}break;case"VP_EDIT_RPC_RESPONSE":this.postMessageToClient({action:t.action,requestId:n,rpcName:t.rpcName,type:"VP_EDIT_RPC_RESPONSE"});break;case"VP_EDIT_RPC_REJECT":this.viewports.get(t.vpId)&&this.postMessageToClient({requestId:n,type:"VP_EDIT_RPC_REJECT",error:t.error});break;case"VIEW_PORT_MENU_REJ":{console.log("send menu error back to client");let{error:a,rpcName:l,vpId:m}=t,y=this.viewports.get(m);y&&this.postMessageToClient({clientViewportId:y.clientViewportId,error:a,rpcName:l,type:"VIEW_PORT_MENU_REJ",requestId:n});break}case"VIEW_PORT_MENU_RESP":if(Ue(t)){let{action:a,rpcName:l}=t;this.awaitResponseToMessage({type:"GET_TABLE_META",table:a.table}).then(m=>{let y=te(m);this.postMessageToClient({rpcName:l,type:"VIEW_PORT_MENU_RESP",action:{...a,tableSchema:y},tableAlreadyOpen:this.isTableOpen(a.table),requestId:n})})}else{let{action:a}=t;this.postMessageToClient({type:"VIEW_PORT_MENU_RESP",action:a||Gt,tableAlreadyOpen:a!==null&&this.isTableOpen(a.table),requestId:n})}break;case"RPC_RESP":{let{method:a,result:l}=t;this.postMessageToClient({type:"RPC_RESP",method:a,result:l,requestId:n})}break;case"VIEW_PORT_RPC_REPONSE":{let{method:a,action:l}=t;this.postMessageToClient({type:"VIEW_PORT_RPC_RESPONSE",rpcName:a,action:l,requestId:n})}break;case"ERROR":_(t.msg);break;default:Wt&&S(\`handleMessageFromServer \${t.type}.\`)}}cacheTableMeta(e){let{module:t,table:n}=e.table,r=\`\${t}:\${n}\`,o=this.cachedTableSchemas.get(r);return o||(o=te(e),this.cachedTableSchemas.set(r,o)),o}isTableOpen(e){if(e){let t=e.table;for(let n of this.viewports.values())if(!n.suspended&&n.table.table===t)return!0}}getActiveLinks(e){return e.filter(t=>{let n=this.viewports.get(t.parentVpId);return n&&!n.suspended})}processUpdates(){this.viewports.forEach(e=>{var t;if(e.hasUpdatesToProcess){let n=e.getClientRows();if(n!==j){let[r,o]=n,i=e.getNewRowCount();(i!==void 0||r&&r.length>0)&&(oe&&x(\`postMessageToClient #\${e.clientViewportId} viewport-update \${o}, \${(t=r==null?void 0:r.length)!=null?t:"no"} rows, size \${i}\`),o&&this.postMessageToClient({clientViewportId:e.clientViewportId,mode:o,rows:r,size:i,type:"viewport-update"}))}}})}};var D,{info:ae,infoEnabled:ue}=w("worker");async function jt(s,e,t,n,r,o,i){let u=await ve(s,e,c=>{ke(c)?postMessage({type:"connection-metrics",messages:c}):Oe(c)?(r(c),c.status==="reconnected"&&D.reconnect()):D.handleMessageFromServer(c)},o,i);D=new J(u,c=>zt(c)),u.requiresLogin&&await D.login(t,n)}function zt(s){postMessage(s)}var Jt=async({data:s})=>{switch(s.type){case"connect":await jt(s.url,s.protocol,s.token,s.username,postMessage,s.retryLimitDisconnect,s.retryLimitStartup),postMessage({type:"connected"});break;case"subscribe":ue&&ae(\`client subscribe: \${JSON.stringify(s)}\`),D.subscribe(s);break;case"unsubscribe":ue&&ae(\`client unsubscribe: \${JSON.stringify(s)}\`),D.unsubscribe(s.viewport);break;default:ue&&ae(\`client message: \${JSON.stringify(s)}\`),D.handleMessageFromClient(s)}};self.addEventListener("message",Jt);postMessage({type:"ready"}); - -`; \ No newline at end of file diff --git a/vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts b/vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts deleted file mode 100644 index b603d8f9c..000000000 --- a/vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts +++ /dev/null @@ -1,388 +0,0 @@ -import { - ClientToServerTableList, - ClientToServerTableMeta, - LinkDescriptorWithLabel, - ServerToClientBody, - ServerToClientMenuSessionTableAction, - ServerToClientViewportRpcResponse, - TypeAheadMethod, - VuuAggregation, - VuuColumns, - VuuGroupBy, - VuuRange, - VuuSort, - VuuTable, -} from "@finos/vuu-protocol-types"; -import { DataSourceFilter } from "@finos/vuu-data-types"; -import { TableSchema, WithRequestId } from "./message-utils"; -import { - DataSourceMenusMessage, - DataSourceVisualLinkCreatedMessage, - DataSourceVisualLinkRemovedMessage, - DataSourceVisualLinksMessage, - RpcResponse, - VuuFeatureInvocationMessage, - VuuFeatureMessage, - WithFullConfig, -} from "./data-source"; -import { GridAction, Selection } from "@finos/vuu-table-types"; -import { WebSocketProtocol } from "./websocket-connection"; - -export interface OpenDialogAction { - type: "OPEN_DIALOG_ACTION"; - tableSchema?: TableSchema; - table?: VuuTable; -} -export interface NoAction { - type: "NO_ACTION"; -} - -export declare type MenuRpcAction = OpenDialogAction | NoAction; - -export type ConnectionStatus = - | "connecting" - | "connection-open-awaiting-session" - | "connected" - | "disconnected" - | "reconnected"; - -export interface ConnectionStatusMessage { - type: "connection-status"; - reason?: string; - retry?: boolean; - status: ConnectionStatus; -} - -export const isConnectionStatusMessage = ( - msg: object | ConnectionStatusMessage -): msg is ConnectionStatusMessage => - (msg as ConnectionStatusMessage).type === "connection-status"; - -export interface ConnectionQualityMetrics { - type: "connection-metrics"; - messagesLength: number; -} - -export const isConnectionQualityMetrics = ( - msg: object -): msg is ConnectionQualityMetrics => - (msg as ConnectionQualityMetrics).type === "connection-metrics"; - -export interface ServerProxySubscribeMessage { - aggregations: VuuAggregation[]; - bufferSize?: number; - columns: VuuColumns; - filter: DataSourceFilter; - groupBy: VuuGroupBy; - range: VuuRange; - sort: VuuSort; - table: VuuTable; - title?: string; - viewport: string; - visualLink?: LinkDescriptorWithLabel; -} - -// export type VuuUIMessageInConnectionStatus = { -// type: 'connection-status'; -// }; - -export type VuuUIMessageInConnected = { - type: "connected"; -}; - -export type VuuUIMessageInWorkerReady = { - type: "ready"; -}; - -export interface ViewportMessageIn { - clientViewportId: string; -} - -// TODO use generic to type result -export interface VuuUIMessageInRPC { - method: string; - result: unknown; - requestId: string; - type: "RPC_RESP"; -} - -export interface VuuUIMessageInRPCEditReject { - error: string; - requestId?: string; - type: "VP_EDIT_RPC_REJECT"; -} - -export interface VuuUIMessageInRPCEditResponse { - action: unknown; - requestId: string; - rpcName: string; - type: "VP_EDIT_RPC_RESPONSE"; -} - -export const messageHasResult = (msg: object): msg is VuuUIMessageInRPC => - typeof (msg as VuuUIMessageInRPC).result !== "undefined"; - -export const isTableSchema = ( - message: VuuUIMessageIn -): message is VuuUIMessageInTableMeta => message.type === "TABLE_META_RESP"; - -export interface VuuUIMessageInTableList { - requestId: string; - type: "TABLE_LIST_RESP"; - tables: VuuTable[]; -} -export interface VuuUIMessageInTableMeta { - requestId: string; - tableSchema: TableSchema; - type: "TABLE_META_RESP"; -} -export interface MenuRpcResponse { - action: MenuRpcAction; - error?: string; - requestId: string; - rpcName?: string; - tableAlreadyOpen?: boolean; - type: "VIEW_PORT_MENU_RESP"; -} -export interface ViewportRpcResponse { - action: ServerToClientViewportRpcResponse["action"]; - requestId: string; - rpcName?: string; - type: "VIEW_PORT_RPC_RESPONSE"; -} -export interface MenuRpcReject extends ViewportMessageIn { - error?: string; - requestId: string; - rpcName?: string; - type: "VIEW_PORT_MENU_REJ"; -} - -export interface VuuUIMessageInMenuRej { - error: string; - requestId: string; - rpcName: string; - type: "VIEW_PORT_MENU_REJ"; -} - -export type VuuUIMessageIn = - | VuuUIMessageInConnected - | VuuUIMessageInWorkerReady - | VuuUIMessageInRPC - | ViewportRpcResponse - | MenuRpcResponse - | MenuRpcReject - | VuuUIMessageInTableList - | VuuUIMessageInTableMeta - | VuuUIMessageInRPCEditReject - | VuuUIMessageInRPCEditResponse; - -export const isErrorResponse = ( - response?: RpcResponse -): response is VuuUIMessageInRPCEditReject => - response !== undefined && "error" in response; - -export const hasAction = ( - response?: RpcResponse -): response is MenuRpcResponse | VuuUIMessageInRPCEditResponse => - response != undefined && "action" in response; - -export interface VuuUIMessageOutConnect { - protocol: WebSocketProtocol; - type: "connect"; - token: string; - url: string; - username?: string; - retryLimitDisconnect?: number; - retryLimitStartup?: number; -} - -export interface VuuUIMessageOutSubscribe extends ServerProxySubscribeMessage { - type: "subscribe"; -} - -export interface VuuUIMessageOutUnsubscribe { - type: "unsubscribe"; - viewport: string; -} -export interface VuuUIMessageOutSuspend { - type: "suspend"; - viewport: string; -} -export interface VuuUIMessageOutResume { - type: "resume"; - viewport: string; -} - -export interface ViewportMessageOut { - viewport: string; -} - -export interface RequestMessage { - requestId: string; -} - -export interface VuuUIMessageOutColumns extends ViewportMessageOut { - type: "setColumns"; - columns: string[]; -} -export interface VuuUIMessageOutViewRange extends ViewportMessageOut { - type: "setViewRange"; - range: { - from: number; - to: number; - }; -} -export interface VuuUIMessageOutAggregate extends ViewportMessageOut { - aggregations: VuuAggregation[]; - type: "aggregate"; -} -export interface VuuUIMessageOutCloseTreeNode extends ViewportMessageOut { - key: string; - type: "closeTreeNode"; -} -export interface VuuUIMessageOutCreateLink extends ViewportMessageOut { - childColumnName: string; - parentColumnName: string; - parentClientVpId: string; - type: "createLink"; -} -export interface VuuUIMessageOutRemoveLink extends ViewportMessageOut { - type: "removeLink"; -} -export interface VuuUIMessageOutSetTitle extends ViewportMessageOut { - title: string; - type: "setTitle"; -} - -export interface VuuUIMessageOutDisable extends ViewportMessageOut { - type: "disable"; -} -export interface VuuUIMessageOutEnable extends ViewportMessageOut { - type: "enable"; -} -export interface VuuUIMessageOutOpenTreeNode extends ViewportMessageOut { - key: string; - type: "openTreeNode"; -} -export interface VuuUIMessageOutResume extends ViewportMessageOut { - type: "resume"; -} - -export interface VuuUIMessageOutSelect extends ViewportMessageOut { - selected: Selection; - type: "select"; -} -export interface VuuUIMessageOutSelectAll extends ViewportMessageOut { - type: "selectAll"; -} -export interface VuuUIMessageOutSelectNone extends ViewportMessageOut { - type: "selectNone"; -} - -export interface VuuUIMessageOutSort extends ViewportMessageOut { - sort: VuuSort; - type: "sort"; -} -export interface VuuUIMessageOutSuspend extends ViewportMessageOut { - type: "suspend"; -} - -export interface VuuUIMessageOutFilter extends ViewportMessageOut { - filter: DataSourceFilter; - type: "filter"; -} -export interface VuuUIMessageOutGroupby extends ViewportMessageOut { - groupBy: VuuGroupBy; - type: "groupBy"; -} - -export interface VuuUIMessageOutConfig extends ViewportMessageOut { - config: WithFullConfig; - type: "config"; -} - -export type VuuUIMessageOutViewport = - | VuuUIMessageOutAggregate - | VuuUIMessageOutCloseTreeNode - | VuuUIMessageOutColumns - | VuuUIMessageOutConfig - | VuuUIMessageOutCreateLink - | VuuUIMessageOutFilter - | VuuUIMessageOutDisable - | VuuUIMessageOutEnable - | VuuUIMessageOutGroupby - | VuuUIMessageOutOpenTreeNode - | VuuUIMessageOutRemoveLink - | VuuUIMessageOutResume - | VuuUIMessageOutSelect - | VuuUIMessageOutSelectAll - | VuuUIMessageOutSelectNone - | VuuUIMessageOutSetTitle - | VuuUIMessageOutSuspend - | VuuUIMessageOutSort - | VuuUIMessageOutViewRange; - -export const isViewporttMessage = ( - msg: object -): msg is VuuUIMessageOutViewport => "viewport" in msg; - -export interface TypeAheadRpcRequest { - method: TypeAheadMethod; - params: [VuuTable, ...string[]]; - type: "RPC_CALL"; -} - -export type VuuUIMessageOut = - | VuuUIMessageOutConnect - | VuuUIMessageOutSubscribe - | VuuUIMessageOutUnsubscribe - | VuuUIMessageOutViewport - | WithRequestId - | WithRequestId; - -export const isSessionTableActionMessage = ( - messageBody: ServerToClientBody -): messageBody is ServerToClientMenuSessionTableAction => - messageBody.type === "VIEW_PORT_MENU_RESP" && - messageBody.action !== null && - isSessionTable(messageBody.action.table); - -export const isSessionTable = (table?: unknown) => { - if ( - table !== null && - typeof table === "object" && - "table" in table && - "module" in table - ) { - return (table as VuuTable).table.startsWith("session"); - } - return false; -}; - -export const isVisualLinksAction = ( - action: GridAction -): action is DataSourceVisualLinksMessage => action.type === "vuu-links"; - -export const isVisualLinkCreatedAction = ( - action: GridAction -): action is DataSourceVisualLinkCreatedMessage => - action.type === "vuu-link-created"; - -export const isVisualLinkRemovedAction = ( - action: GridAction -): action is DataSourceVisualLinkRemovedMessage => - action.type === "vuu-link-removed"; - -export const isViewportMenusAction = ( - action: GridAction -): action is DataSourceMenusMessage => action.type === "vuu-menu"; - -export const isVuuFeatureAction = ( - action: GridAction -): action is VuuFeatureMessage => - isViewportMenusAction(action) || isVisualLinksAction(action); - -export const isVuuFeatureInvocation = ( - action: GridAction -): action is VuuFeatureInvocationMessage => - action.type === "vuu-link-created" || action.type === "vuu-link-removed"; diff --git a/vuu-ui/packages/vuu-datatable/package.json b/vuu-ui/packages/vuu-datatable/package.json index f2edaae4c..56914915a 100644 --- a/vuu-ui/packages/vuu-datatable/package.json +++ b/vuu-ui/packages/vuu-datatable/package.json @@ -20,8 +20,8 @@ "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } } diff --git a/vuu-ui/packages/vuu-datatable/src/filter-table/FilterTable.tsx b/vuu-ui/packages/vuu-datatable/src/filter-table/FilterTable.tsx index 5edd19733..7a4f5a3f5 100644 --- a/vuu-ui/packages/vuu-datatable/src/filter-table/FilterTable.tsx +++ b/vuu-ui/packages/vuu-datatable/src/filter-table/FilterTable.tsx @@ -1,7 +1,7 @@ import { FilterBar, FilterBarProps } from "@finos/vuu-filters"; import { Table, TableProps } from "@finos/vuu-table"; import { HTMLAttributes } from "react"; -import cx from "classnames"; +import cx from "clsx"; import "./FilterTable.css"; diff --git a/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx b/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx index 4a59bf2b4..49690c556 100644 --- a/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx +++ b/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx @@ -1,7 +1,7 @@ import { TableProps } from "@finos/vuu-table"; import { JsonData } from "@finos/vuu-utils"; import { Table } from "@finos/vuu-table"; -import { JsonDataSource } from "@finos/vuu-data"; +import { JsonDataSource } from "@finos/vuu-data-local"; import { useEffect, useMemo, useRef } from "react"; import { TableConfig } from "@finos/vuu-table-types"; diff --git a/vuu-ui/packages/vuu-filters/package.json b/vuu-ui/packages/vuu-filters/package.json index e7e0ab976..e312c2cbb 100644 --- a/vuu-ui/packages/vuu-filters/package.json +++ b/vuu-ui/packages/vuu-filters/package.json @@ -22,12 +22,11 @@ "@finos/vuu-popups": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/lab": "1.0.0-alpha.15", + "@salt-ds/core": "1.13.2", "uuid": "9.0.0" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } } diff --git a/vuu-ui/packages/vuu-filters/src/filter-bar/FilterBar.tsx b/vuu-ui/packages/vuu-filters/src/filter-bar/FilterBar.tsx index 02e7f71f6..d40e0fa78 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-bar/FilterBar.tsx +++ b/vuu-ui/packages/vuu-filters/src/filter-bar/FilterBar.tsx @@ -1,10 +1,9 @@ -import { TableSchema } from "@finos/vuu-data"; -import { DataSourceFilter } from "@finos/vuu-data-types"; +import { DataSourceFilter, TableSchema } from "@finos/vuu-data-types"; import { Filter } from "@finos/vuu-filter-types"; import { ActiveItemChangeHandler, Toolbar } from "@finos/vuu-layout"; import { Prompt } from "@finos/vuu-popups"; import { Button } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, ReactElement, useRef } from "react"; import { FilterBuilderMenu } from "../filter-builder-menu"; import { FilterClauseEditor, FilterClauseEditorProps } from "../filter-clause"; diff --git a/vuu-ui/packages/vuu-filters/src/filter-bar/useFilterBar.ts b/vuu-ui/packages/vuu-filters/src/filter-bar/useFilterBar.ts index e424935fc..551193bd9 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-bar/useFilterBar.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-bar/useFilterBar.ts @@ -9,12 +9,12 @@ import { NavigationOutOfBoundsHandler, } from "@finos/vuu-layout"; import { PromptProps } from "@finos/vuu-popups"; +import { EditableLabelProps } from "@finos/vuu-ui-controls"; import { dispatchMouseEvent, filterAsQuery, isMultiClauseFilter, } from "@finos/vuu-utils"; -import { EditableLabelProps } from "@salt-ds/lab"; import { FocusEventHandler, KeyboardEvent, diff --git a/vuu-ui/packages/vuu-filters/src/filter-bar/useFilters.ts b/vuu-ui/packages/vuu-filters/src/filter-bar/useFilters.ts index 1456b6b9c..4a85266d7 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-bar/useFilters.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-bar/useFilters.ts @@ -1,8 +1,8 @@ -import { useControlled } from "@finos/vuu-ui-controls"; +import { TableSchema } from "@finos/vuu-data-types"; import { Filter, NamedFilter } from "@finos/vuu-filter-types"; -import { useCallback } from "react"; -import { TableSchema } from "packages/vuu-data/src"; import { useLayoutManager } from "@finos/vuu-shell"; +import { useControlled } from "@finos/vuu-ui-controls"; +import { useCallback } from "react"; export interface FiltersHookProps { defaultFilters?: Filter[]; diff --git a/vuu-ui/packages/vuu-filters/src/filter-clause/ExpandoCombobox.tsx b/vuu-ui/packages/vuu-filters/src/filter-clause/ExpandoCombobox.tsx index 5c16d43c1..c8ea60e27 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-clause/ExpandoCombobox.tsx +++ b/vuu-ui/packages/vuu-filters/src/filter-clause/ExpandoCombobox.tsx @@ -6,7 +6,7 @@ import { SelectionStrategy, SingleSelectionHandler, } from "@finos/vuu-ui-controls"; -import cx from "classnames"; +import cx from "clsx"; import { FormEvent, ForwardedRef, diff --git a/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx b/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx index bcb364069..219695598 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx +++ b/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx @@ -1,9 +1,9 @@ -import { TableSchema } from "@finos/vuu-data"; +import { TableSchema } from "@finos/vuu-data-types"; import { SuggestionFetcher } from "@finos/vuu-data-react"; import { ColumnDescriptor } from "@finos/vuu-table-types"; import { FilterClause } from "@finos/vuu-filter-types"; import { CloseReason } from "@finos/vuu-ui-controls"; -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, useCallback } from "react"; import { ExpandoCombobox } from "./ExpandoCombobox"; import { NumericInput } from "./NumericInput"; diff --git a/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts b/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts index f9c6bfa05..867e9c7dd 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts @@ -1,12 +1,14 @@ -import { ColumnDescriptor } from "@finos/vuu-table-types"; +import { TableSchema } from "@finos/vuu-data-types"; import { FilterClause, FilterClauseOp } from "@finos/vuu-filter-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { isMultiValueFilter, isSingleValueFilter, isValidFilterClauseOp, } from "@finos/vuu-utils"; -import { getColumnByName, TableSchema } from "@finos/vuu-data"; +import { getColumnByName } from "@finos/vuu-data-remote"; +import { SingleSelectionHandler } from "@finos/vuu-ui-controls"; import { KeyboardEvent, KeyboardEventHandler, @@ -16,7 +18,6 @@ import { useRef, useState, } from "react"; -import { SingleSelectionHandler } from "@finos/vuu-ui-controls/src"; const cursorAtTextStart = (input: HTMLInputElement) => input.selectionStart === 0; diff --git a/vuu-ui/packages/vuu-filters/src/filter-input/useCodeMirrorEditor.ts b/vuu-ui/packages/vuu-filters/src/filter-input/useCodeMirrorEditor.ts index 9ffb76104..cd7826b5a 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-input/useCodeMirrorEditor.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-input/useCodeMirrorEditor.ts @@ -12,7 +12,7 @@ import { } from "@finos/vuu-codemirror"; import { walkTree } from "@finos/vuu-filter-parser"; import { Filter } from "@finos/vuu-filter-types"; -import cx from "classnames"; +import cx from "clsx"; import { MutableRefObject, useEffect, useMemo, useRef } from "react"; import { filterLanguageSupport } from "./FilterLanguage"; import { vuuHighlighting } from "./highlighting"; diff --git a/vuu-ui/packages/vuu-filters/src/filter-pill-menu/FilterPillMenu.tsx b/vuu-ui/packages/vuu-filters/src/filter-pill-menu/FilterPillMenu.tsx index 76a44b32d..7b85f1c64 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-pill-menu/FilterPillMenu.tsx +++ b/vuu-ui/packages/vuu-filters/src/filter-pill-menu/FilterPillMenu.tsx @@ -5,7 +5,7 @@ import { MenuBuilder, } from "@finos/vuu-data-types"; import { useMemo } from "react"; -import cx from "classnames"; +import cx from "clsx"; import "./FilterPillMenu.css"; import { diff --git a/vuu-ui/packages/vuu-filters/src/filter-pill/FilterPill.tsx b/vuu-ui/packages/vuu-filters/src/filter-pill/FilterPill.tsx index 356a19af6..656111ba2 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-pill/FilterPill.tsx +++ b/vuu-ui/packages/vuu-filters/src/filter-pill/FilterPill.tsx @@ -1,10 +1,9 @@ import { MenuActionHandler } from "@finos/vuu-data-types"; import { Filter } from "@finos/vuu-filter-types"; -import { useId } from "@finos/vuu-layout"; -import { PopupCloseCallback, Tooltip, useTooltip } from "@finos/vuu-popups/src"; +import { PopupCloseCallback, Tooltip, useTooltip } from "@finos/vuu-popups"; import { EditableLabel, EditableLabelProps } from "@finos/vuu-ui-controls"; -import { filterAsQuery, isMultiClauseFilter } from "@finos/vuu-utils"; -import cx from "classnames"; +import { filterAsQuery, isMultiClauseFilter, useId } from "@finos/vuu-utils"; +import cx from "clsx"; import { HTMLAttributes, useCallback, useRef } from "react"; import { FilterPillMenu } from "../filter-pill-menu"; import { filterClauses } from "../filter-utils"; diff --git a/vuu-ui/packages/vuu-icons/index.css b/vuu-ui/packages/vuu-icons/index.css index df0ae24f9..ddc71b731 100644 --- a/vuu-ui/packages/vuu-icons/index.css +++ b/vuu-ui/packages/vuu-icons/index.css @@ -84,8 +84,8 @@ span[data-icon] { background-color: var(--vuu-icon-color, var(--saltIcon-color, var(--salt-text-secondary-foreground))); left: var(--vuu-icon-left, auto); height: var(--vuu-icon-height, var(--vuu-icon-size, 12px)); - -webkit-mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size); mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size); + -webkit-mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; position: absolute; diff --git a/vuu-ui/packages/vuu-layout/package.json b/vuu-ui/packages/vuu-layout/package.json index 62d410a7a..929fd6860 100644 --- a/vuu-ui/packages/vuu-layout/package.json +++ b/vuu-ui/packages/vuu-layout/package.json @@ -11,7 +11,8 @@ }, "types": "src/index.ts", "dependencies": { - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", @@ -20,8 +21,9 @@ "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" - } + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" + }, + "sideEffects": false } diff --git a/vuu-ui/packages/vuu-layout/src/DraggableLayout.tsx b/vuu-ui/packages/vuu-layout/src/DraggableLayout.tsx index db6b789bb..82c656a70 100644 --- a/vuu-ui/packages/vuu-layout/src/DraggableLayout.tsx +++ b/vuu-ui/packages/vuu-layout/src/DraggableLayout.tsx @@ -1,4 +1,4 @@ -import classnames from "classnames"; +import classnames from "clsx"; import { ForwardedRef, forwardRef, HTMLAttributes } from "react"; import { registerComponent } from "./registry/ComponentRegistry"; diff --git a/vuu-ui/packages/vuu-layout/src/dock-layout/DockLayout.tsx b/vuu-ui/packages/vuu-layout/src/dock-layout/DockLayout.tsx index 88a112f2d..61f60f00a 100644 --- a/vuu-ui/packages/vuu-layout/src/dock-layout/DockLayout.tsx +++ b/vuu-ui/packages/vuu-layout/src/dock-layout/DockLayout.tsx @@ -1,5 +1,5 @@ import { partition } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, ReactElement } from "react"; import { registerComponent } from "../registry/ComponentRegistry"; import Drawer from "./Drawer"; diff --git a/vuu-ui/packages/vuu-layout/src/dock-layout/Drawer.tsx b/vuu-ui/packages/vuu-layout/src/dock-layout/Drawer.tsx index 673296b26..6b45bcf4c 100644 --- a/vuu-ui/packages/vuu-layout/src/dock-layout/Drawer.tsx +++ b/vuu-ui/packages/vuu-layout/src/dock-layout/Drawer.tsx @@ -1,5 +1,5 @@ import { Button, useControlled } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { CSSProperties, HTMLAttributes, useCallback } from "react"; import "./Drawer.css"; diff --git a/vuu-ui/packages/vuu-layout/src/drag-drop/DropMenu.tsx b/vuu-ui/packages/vuu-layout/src/drag-drop/DropMenu.tsx index f886a73a0..7c66b693f 100644 --- a/vuu-ui/packages/vuu-layout/src/drag-drop/DropMenu.tsx +++ b/vuu-ui/packages/vuu-layout/src/drag-drop/DropMenu.tsx @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes } from "react"; import { DropTarget } from "./DropTarget"; diff --git a/vuu-ui/packages/vuu-layout/src/flexbox/Flexbox.tsx b/vuu-ui/packages/vuu-layout/src/flexbox/Flexbox.tsx index 09c2cec87..506de41fa 100644 --- a/vuu-ui/packages/vuu-layout/src/flexbox/Flexbox.tsx +++ b/vuu-ui/packages/vuu-layout/src/flexbox/Flexbox.tsx @@ -1,5 +1,5 @@ import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { CSSProperties, ForwardedRef, forwardRef } from "react"; import { FlexboxProps } from "./flexboxTypes"; import { useSplitterResizing } from "./useSplitterResizing"; diff --git a/vuu-ui/packages/vuu-layout/src/flexbox/FluidGrid.tsx b/vuu-ui/packages/vuu-layout/src/flexbox/FluidGrid.tsx index b582ac163..da9cb9d74 100644 --- a/vuu-ui/packages/vuu-layout/src/flexbox/FluidGrid.tsx +++ b/vuu-ui/packages/vuu-layout/src/flexbox/FluidGrid.tsx @@ -1,5 +1,5 @@ import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { ForwardedRef, forwardRef, useMemo } from "react"; import { useBreakpoints } from "../responsive"; import { asReactElements } from "../utils"; diff --git a/vuu-ui/packages/vuu-layout/src/flexbox/Splitter.tsx b/vuu-ui/packages/vuu-layout/src/flexbox/Splitter.tsx index 342b9f630..227d16779 100644 --- a/vuu-ui/packages/vuu-layout/src/flexbox/Splitter.tsx +++ b/vuu-ui/packages/vuu-layout/src/flexbox/Splitter.tsx @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import React, { HTMLAttributes, KeyboardEvent, diff --git a/vuu-ui/packages/vuu-layout/src/index.ts b/vuu-ui/packages/vuu-layout/src/index.ts index 039e77a90..e8fb4cef9 100644 --- a/vuu-ui/packages/vuu-layout/src/index.ts +++ b/vuu-ui/packages/vuu-layout/src/index.ts @@ -5,7 +5,6 @@ export * from "./DraggableLayout"; export * from "./flexbox"; export { Action } from "./layout-action"; export * from "./layout-header"; -export * from "./layout-persistence"; export * from "./layout-provider"; export * from "./layout-reducer"; export * from "./layout-view"; diff --git a/vuu-ui/packages/vuu-layout/src/layout-header/ActionButton.tsx b/vuu-ui/packages/vuu-layout/src/layout-header/ActionButton.tsx index bd1dc385d..9baf38292 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-header/ActionButton.tsx +++ b/vuu-ui/packages/vuu-layout/src/layout-header/ActionButton.tsx @@ -1,22 +1,33 @@ -import classnames from 'classnames'; -import { HTMLAttributes, MouseEvent } from 'react'; +import classnames from "clsx"; +import { HTMLAttributes, MouseEvent } from "react"; -export interface ActionButtonProps extends Omit, 'onClick'> { - actionId: 'maximize' | 'minimize' | 'restore' | 'tearout'; +export interface ActionButtonProps + extends Omit, "onClick"> { + actionId: "maximize" | "minimize" | "restore" | "tearout"; iconName?: string; - onClick: (evt: MouseEvent, actionId: 'maximize' | 'minimize' | 'restore' | 'tearout') => void; + onClick: ( + evt: MouseEvent, + actionId: "maximize" | "minimize" | "restore" | "tearout" + ) => void; } -const ActionButton = ({ actionId, className, iconName, onClick, ...props }: ActionButtonProps) => { +const ActionButton = ({ + actionId, + className, + iconName, + onClick, + ...props +}: ActionButtonProps) => { const handleClick = (evt: MouseEvent) => { onClick(evt, actionId); }; return ( + title="Close View" + > ); }; diff --git a/vuu-ui/packages/vuu-layout/src/layout-header/Header.tsx b/vuu-ui/packages/vuu-layout/src/layout-header/Header.tsx index e128076cf..36f59da79 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-header/Header.tsx +++ b/vuu-ui/packages/vuu-layout/src/layout-header/Header.tsx @@ -1,6 +1,6 @@ import { EditableLabel } from "@finos/vuu-ui-controls"; import { Button } from "@salt-ds/core"; -import { default as classnames, default as cx } from "classnames"; +import { default as classnames, default as cx } from "clsx"; import { cloneElement, HTMLAttributes, diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/index.ts b/vuu-ui/packages/vuu-layout/src/layout-persistence/index.ts deleted file mode 100644 index 06c29a51c..000000000 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./defaultApplicationJson"; -export * from "./LayoutPersistenceManager"; -export * from "./LocalLayoutPersistenceManager"; -export * from "./RemoteLayoutPersistenceManager"; -export * from "./useLayoutContextMenuItems"; diff --git a/vuu-ui/packages/vuu-layout/src/layout-reducer/layoutTypes.ts b/vuu-ui/packages/vuu-layout/src/layout-reducer/layoutTypes.ts index de4883166..30519415d 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-reducer/layoutTypes.ts +++ b/vuu-ui/packages/vuu-layout/src/layout-reducer/layoutTypes.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { NamedFilter } from "packages/vuu-filter-types"; +import { NamedFilter } from "@finos/vuu-filter-types"; import { CSSProperties, ReactElement } from "react"; import { DragDropRect, DragInstructions } from "../drag-drop"; import { DropTarget } from "../drag-drop/DropTarget"; diff --git a/vuu-ui/packages/vuu-layout/src/layout-view/View.tsx b/vuu-ui/packages/vuu-layout/src/layout-view/View.tsx index aef7a57b0..0d9109992 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-view/View.tsx +++ b/vuu-ui/packages/vuu-layout/src/layout-view/View.tsx @@ -1,5 +1,6 @@ +import { useId } from "@finos/vuu-utils"; import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import React, { ForwardedRef, forwardRef, @@ -11,7 +12,6 @@ import React, { } from "react"; import { Header as VuuHeader } from "../layout-header/Header"; import { registerComponent } from "../registry/ComponentRegistry"; -import { useId } from "../utils"; import { useView } from "./useView"; import { useViewResize } from "./useViewResize"; import { ViewContext, ViewContextAPI } from "./ViewContext"; diff --git a/vuu-ui/packages/vuu-layout/src/layout-view/useViewActionDispatcher.ts b/vuu-ui/packages/vuu-layout/src/layout-view/useViewActionDispatcher.ts index 6fc2fb2eb..1fd356a6f 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-view/useViewActionDispatcher.ts +++ b/vuu-ui/packages/vuu-layout/src/layout-view/useViewActionDispatcher.ts @@ -1,4 +1,4 @@ -import { DataSource } from "@finos/vuu-data"; +import { DataSource } from "@finos/vuu-data-types"; import { ReactElement, RefObject, diff --git a/vuu-ui/packages/vuu-layout/src/measured-container/MeasuredContainer.tsx b/vuu-ui/packages/vuu-layout/src/measured-container/MeasuredContainer.tsx index a76471c5c..bf8f9571c 100644 --- a/vuu-ui/packages/vuu-layout/src/measured-container/MeasuredContainer.tsx +++ b/vuu-ui/packages/vuu-layout/src/measured-container/MeasuredContainer.tsx @@ -1,7 +1,7 @@ import { CSSProperties, forwardRef, ForwardedRef, HTMLAttributes } from "react"; import { MeasuredSize, useMeasuredContainer } from "./useMeasuredContainer"; import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import "./MeasuredContainer.css"; diff --git a/vuu-ui/packages/vuu-layout/src/overflow-container/OverflowContainer.tsx b/vuu-ui/packages/vuu-layout/src/overflow-container/OverflowContainer.tsx index da47264c6..451ffe79f 100644 --- a/vuu-ui/packages/vuu-layout/src/overflow-container/OverflowContainer.tsx +++ b/vuu-ui/packages/vuu-layout/src/overflow-container/OverflowContainer.tsx @@ -1,8 +1,7 @@ import { PopupMenu, PopupMenuProps } from "@finos/vuu-popups"; -import { orientationType } from "@finos/vuu-utils"; -import { useId } from "@finos/vuu-layout"; +import { orientationType, useId } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import React, { CSSProperties, ForwardedRef, diff --git a/vuu-ui/packages/vuu-layout/src/overflow-container/useOverflowContainer.ts b/vuu-ui/packages/vuu-layout/src/overflow-container/useOverflowContainer.ts index 3b91b19f0..0966fe4e1 100644 --- a/vuu-ui/packages/vuu-layout/src/overflow-container/useOverflowContainer.ts +++ b/vuu-ui/packages/vuu-layout/src/overflow-container/useOverflowContainer.ts @@ -1,8 +1,11 @@ import { MenuActionHandler, MenuBuilder } from "@finos/vuu-data-types"; import { useDragDropNext as useDragDrop } from "@finos/vuu-ui-controls"; -import { isValidNumber, MEASURES } from "@finos/vuu-utils"; +import { + isValidNumber, + MEASURES, + useLayoutEffectSkipFirst, +} from "@finos/vuu-utils"; import { useCallback, useMemo, useRef, useState } from "react"; -import { useLayoutEffectSkipFirst } from "../utils"; import { applyOverflowClassToWrappedItems, removeOverflowIndicatorIfNoLongerNeeded, diff --git a/vuu-ui/packages/vuu-layout/src/palette/Palette.tsx b/vuu-ui/packages/vuu-layout/src/palette/Palette.tsx index 2fd0bfe93..bd23f0097 100644 --- a/vuu-ui/packages/vuu-layout/src/palette/Palette.tsx +++ b/vuu-ui/packages/vuu-layout/src/palette/Palette.tsx @@ -5,7 +5,7 @@ import { ListItemProps, ListProps, } from "@finos/vuu-ui-controls"; -import cx from "classnames"; +import cx from "clsx"; import { cloneElement, HTMLAttributes, diff --git a/vuu-ui/packages/vuu-layout/src/placeholder/LayoutStartPanel.tsx b/vuu-ui/packages/vuu-layout/src/placeholder/LayoutStartPanel.tsx index 3369d32e0..2a73ac743 100644 --- a/vuu-ui/packages/vuu-layout/src/placeholder/LayoutStartPanel.tsx +++ b/vuu-ui/packages/vuu-layout/src/placeholder/LayoutStartPanel.tsx @@ -1,6 +1,6 @@ import { Button } from "@salt-ds/core"; import { HTMLAttributes, useMemo, useState } from "react"; -import { QueryReponse, useViewContext } from "@finos/vuu-layout"; +import { QueryReponse, useViewContext } from "../layout-view"; import "./LayoutStartPanel.css"; diff --git a/vuu-ui/packages/vuu-layout/src/placeholder/Placeholder.tsx b/vuu-ui/packages/vuu-layout/src/placeholder/Placeholder.tsx index b1f424085..3bc656d3a 100644 --- a/vuu-ui/packages/vuu-layout/src/placeholder/Placeholder.tsx +++ b/vuu-ui/packages/vuu-layout/src/placeholder/Placeholder.tsx @@ -1,7 +1,7 @@ -import cx from "classnames"; +import cx from "clsx"; import { registerComponent } from "../registry/ComponentRegistry"; import { LayoutStartPanel } from "./LayoutStartPanel"; -import { View, ViewProps } from "@finos/vuu-layout"; +import { View, ViewProps } from "../layout-view"; import "./Placeholder.css"; diff --git a/vuu-ui/packages/vuu-layout/src/stack/Stack.tsx b/vuu-ui/packages/vuu-layout/src/stack/Stack.tsx index c9ad2a635..a7eac8751 100644 --- a/vuu-ui/packages/vuu-layout/src/stack/Stack.tsx +++ b/vuu-ui/packages/vuu-layout/src/stack/Stack.tsx @@ -1,5 +1,6 @@ import { Tab, Tabstrip, TabstripProps } from "@finos/vuu-ui-controls"; -import cx from "classnames"; +import { useId } from "@finos/vuu-utils"; +import cx from "clsx"; import React, { ForwardedRef, forwardRef, @@ -9,7 +10,6 @@ import React, { useRef, } from "react"; import { getDefaultTabLabel } from "../layout-reducer"; -import { useId } from "../utils"; import { StackProps } from "./stackTypes"; import "./Stack.css"; @@ -138,6 +138,7 @@ export const Stack = forwardRef(function Stack( allowDragDrop={TabstripProps.allowDragDrop !== false} animateSelectionThumb className={cx("vuuTabHeader", tabstripClassName)} + aria-label="data tabs" keyBoardActivation={keyBoardActivation} onActiveChange={onTabSelectionChanged} onAddTab={onAddTab} diff --git a/vuu-ui/packages/vuu-layout/src/stack/StackLayout.tsx b/vuu-ui/packages/vuu-layout/src/stack/StackLayout.tsx index efa3e069d..cef23cf15 100644 --- a/vuu-ui/packages/vuu-layout/src/stack/StackLayout.tsx +++ b/vuu-ui/packages/vuu-layout/src/stack/StackLayout.tsx @@ -1,4 +1,4 @@ -import { useIdMemo as useId } from "@salt-ds/core"; +import { useId } from "@finos/vuu-utils"; import React, { useCallback, useRef } from "react"; import { useLayoutCreateNewChild, @@ -10,9 +10,9 @@ import { usePersistentState } from "../use-persistent-state"; import { Stack } from "./Stack"; import { StackProps, TabLabelFactory } from "./stackTypes"; import { getDefaultTabLabel } from "../layout-reducer"; +import { Placeholder } from "../placeholder"; import "./Stack.css"; -import { Placeholder } from "../placeholder"; const defaultCreateNewChild = () => ( { const isArray = Array.isArray(children); const count = isArray ? children.length : Children.count(children); @@ -27,21 +15,3 @@ export const asReactElements = (children: ReactNode): ReactElement[] => { return EMPTY_ARRAY; } }; - -export const useLayoutEffectSkipFirst = ( - func: EffectCallback, - deps: DependencyList -) => { - const goodToGo = useRef(false); - useLayoutEffect(() => { - if (goodToGo.current) { - func(); - } else { - goodToGo.current = true; - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, deps); -}; - -export const useId = (id?: string) => - useMemo(() => id ?? `vuu-${++vuuComponentIdCount}`, [id]); diff --git a/vuu-ui/packages/vuu-popups/package.json b/vuu-ui/packages/vuu-popups/package.json index 3b6dff1f3..3fc887e8d 100644 --- a/vuu-ui/packages/vuu-popups/package.json +++ b/vuu-ui/packages/vuu-popups/package.json @@ -10,19 +10,16 @@ "type-defs": "node ../../scripts/build-type-defs.mjs" }, "dependencies": { - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15", - "@finos/vuu-data": "0.0.26", + "@salt-ds/core": "1.13.2", "@finos/vuu-data-types": "0.0.26", "@finos/vuu-layout": "0.0.26", - "@finos/vuu-shell": "0.0.26", "@finos/vuu-utils": "0.0.26", "@finos/vuu-ui-controls": "0.0.26" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" - } + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" + }, + "sideEffects": false } diff --git a/vuu-ui/packages/vuu-popups/src/dialog-header/DialogHeader.tsx b/vuu-ui/packages/vuu-popups/src/dialog-header/DialogHeader.tsx index 55e18ec5d..b745d3a0c 100644 --- a/vuu-ui/packages/vuu-popups/src/dialog-header/DialogHeader.tsx +++ b/vuu-ui/packages/vuu-popups/src/dialog-header/DialogHeader.tsx @@ -1,6 +1,6 @@ import { Button, Text } from "@salt-ds/core"; import { HTMLAttributes } from "react"; -import cx from "classnames"; +import cx from "clsx"; import "./DialogHeader.css"; diff --git a/vuu-ui/packages/vuu-popups/src/dialog/Dialog.css b/vuu-ui/packages/vuu-popups/src/dialog/Dialog.css index e78d547bd..1d32f4bd5 100644 --- a/vuu-ui/packages/vuu-popups/src/dialog/Dialog.css +++ b/vuu-ui/packages/vuu-popups/src/dialog/Dialog.css @@ -3,8 +3,10 @@ border: var(--vuuDialog-border, solid 1px #ccc); border-radius: 5px; padding: var(--vuuDialog-padding, 16px); + position: relative; box-shadow: var(--salt-overlayable-shadow, none); height: var(--vuuDialog-height, fit-content); + overflow: visible; width: var(--vuuDialog-width, fit-content); } diff --git a/vuu-ui/packages/vuu-popups/src/dialog/Dialog.tsx b/vuu-ui/packages/vuu-popups/src/dialog/Dialog.tsx index 6338c682d..4c523fbbe 100644 --- a/vuu-ui/packages/vuu-popups/src/dialog/Dialog.tsx +++ b/vuu-ui/packages/vuu-popups/src/dialog/Dialog.tsx @@ -1,50 +1,95 @@ -import { Scrim } from "@salt-ds/lab"; -import cx from "classnames"; -import { HTMLAttributes, useCallback, useRef } from "react"; -import { Portal } from "../portal"; +import cx from "clsx"; +import { useThemeAttributes } from "@finos/vuu-utils"; +import { HTMLAttributes, useCallback, useLayoutEffect, useRef } from "react"; import { DialogHeader } from "../dialog-header"; import "./Dialog.css"; +import { PopupComponentProps, useAnchoredPosition } from "../popup"; const classBase = "vuuDialog"; -export interface DialogProps extends HTMLAttributes { +const AnchorBody = { current: document.body }; +const EMPTY_PROPS = {}; + +export interface DialogProps extends HTMLAttributes { + PopupProps?: Partial; isOpen?: boolean; onClose?: () => void; hideCloseButton?: boolean; } export const Dialog = ({ + PopupProps = EMPTY_PROPS, children, className, isOpen = false, onClose, + style, title, hideCloseButton = false, - ...props + ...htmlAttributes }: DialogProps) => { - const root = useRef(null); + const { + anchorElement = AnchorBody, + offsetLeft = 0, + offsetTop = 0, + placement = "auto", + } = PopupProps; + + const rootRef = useRef(null); + const portalRef = useRef(null); + const [themeClass, densityClass, dataMode] = useThemeAttributes(); + const { position } = useAnchoredPosition({ + anchorElement, + offsetLeft, + offsetTop, + placement, + }); const close = useCallback(() => { onClose?.(); }, [onClose]); - if (!isOpen) { - return null; - } + // if (!isOpen) { + // return null; + // } + + useLayoutEffect(() => { + if (rootRef.current) { + if (isOpen) { + rootRef.current.showModal(); + + const { left, top } = rootRef.current.getBoundingClientRect(); + if (portalRef.current) { + portalRef.current.style.cssText = `left:-${left}px;position:absolute;top:-${top}px;`; + } + } else { + rootRef.current.close(); + } + if (placement.endsWith("center")) { + const { width } = rootRef.current.getBoundingClientRect(); + rootRef.current.style.marginLeft = `-${width / 2}px`; + } + } + }, [isOpen, placement]); return ( - - -
- -
{children}
-
-
-
+ + +
{children}
+
+
); }; diff --git a/vuu-ui/packages/vuu-popups/src/menu/ContextMenu.tsx b/vuu-ui/packages/vuu-popups/src/menu/ContextMenu.tsx index 6d5d2cdd3..21d52e75b 100644 --- a/vuu-ui/packages/vuu-popups/src/menu/ContextMenu.tsx +++ b/vuu-ui/packages/vuu-popups/src/menu/ContextMenu.tsx @@ -1,15 +1,11 @@ +import { useId } from "@finos/vuu-utils"; import { useCallback, useRef } from "react"; +import { PopupCloseCallback, PopupComponent } from "../popup"; +import { Portal, PortalProps } from "../portal"; import { MenuList, MenuListProps } from "./MenuList"; import { useCascade } from "./use-cascade"; import { useItemsWithIdsNext } from "./use-items-with-ids-next"; -import { useId } from "@finos/vuu-layout"; -import { PopupCloseCallback } from "../popup"; import { ContextMenuOptions } from "./useContextMenu"; -import { - PopupComponent as Popup, - Portal, - PortalProps, -} from "@finos/vuu-popups"; export interface ContextMenuProps extends Omit { PortalProps?: Partial; @@ -97,7 +93,7 @@ export const ContextMenu = ({ const childMenuId = getChildMenuId(i); return ( - {menus[menuId]} - + ); })} diff --git a/vuu-ui/packages/vuu-popups/src/menu/MenuList.css b/vuu-ui/packages/vuu-popups/src/menu/MenuList.css index 16c33a0d5..35ede9d87 100644 --- a/vuu-ui/packages/vuu-popups/src/menu/MenuList.css +++ b/vuu-ui/packages/vuu-popups/src/menu/MenuList.css @@ -65,8 +65,8 @@ .vuuMenuItem[aria-haspopup='true']:after { content: var(--menu-item-twisty-content); + mask: var(--vuu-svg-chevron-right) center center/8px 8px no-repeat; -webkit-mask: var(--vuu-svg-chevron-right) center center/8px 8px no-repeat; - mask: var(---vuu-svg-chevron-right) center center/8px 8px no-repeat; background-color: var(--menu-item-twisty-color); height: 16px; left: var(--menu-item-twisty-left); diff --git a/vuu-ui/packages/vuu-popups/src/menu/MenuList.tsx b/vuu-ui/packages/vuu-popups/src/menu/MenuList.tsx index 08eb66c41..7b41e5d5c 100644 --- a/vuu-ui/packages/vuu-popups/src/menu/MenuList.tsx +++ b/vuu-ui/packages/vuu-popups/src/menu/MenuList.tsx @@ -1,3 +1,4 @@ +import cx from "clsx"; import React, { FC, HTMLAttributes, @@ -7,11 +8,10 @@ import React, { useMemo, useRef, } from "react"; -import cx from "classnames"; //TODO do we want this dependency ? -import { useId } from "@finos/vuu-layout"; -import { useKeyboardNavigation } from "./use-keyboard-navigation"; +import { useId } from "@finos/vuu-utils"; import { isMenuItemGroup } from "./use-items-with-ids-next"; +import { useKeyboardNavigation } from "./use-keyboard-navigation"; import "./MenuList.css"; diff --git a/vuu-ui/packages/vuu-popups/src/menu/useContextMenu.tsx b/vuu-ui/packages/vuu-popups/src/menu/useContextMenu.tsx index 54e1355a7..3ddb6ebdb 100644 --- a/vuu-ui/packages/vuu-popups/src/menu/useContextMenu.tsx +++ b/vuu-ui/packages/vuu-popups/src/menu/useContextMenu.tsx @@ -3,7 +3,10 @@ import { MenuActionHandler, MenuBuilder, } from "@finos/vuu-data-types"; -import { isGroupMenuItemDescriptor } from "@finos/vuu-utils"; +import { + isGroupMenuItemDescriptor, + useThemeAttributes, +} from "@finos/vuu-utils"; import { cloneElement, useCallback, useContext, useMemo } from "react"; import { MenuActionClosePopup, @@ -14,7 +17,6 @@ import { import { ContextMenu, ContextMenuProps } from "./ContextMenu"; import { MenuItem, MenuItemGroup } from "./MenuList"; import { ContextMenuContext } from "./context-menu-provider"; -import { useThemeAttributes } from "@finos/vuu-shell"; export type ContextMenuOptions = { [key: string]: unknown; diff --git a/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx b/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx index 9fd2c67e9..96fa49e33 100644 --- a/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx +++ b/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx @@ -1,5 +1,5 @@ import React, { useState, useContext, useCallback, useEffect } from "react"; -import classNames from "classnames"; +import classNames from "clsx"; import { getUniqueId } from "@finos/vuu-utils"; import "./notifications.css"; @@ -93,9 +93,7 @@ export const ToastNotification = (props: ToastNotificationProps) => { const [right, setRight] = useState(-toastWidth - toastContainerRightPadding); useEffect(() => { - setTimeout( - () => setRight(toastContainerRightPadding) - ); + setTimeout(() => setRight(toastContainerRightPadding)); if (animated) { setTimeout( diff --git a/vuu-ui/packages/vuu-popups/src/popup-menu/PopupMenu.tsx b/vuu-ui/packages/vuu-popups/src/popup-menu/PopupMenu.tsx index 110cc7513..be5671d0e 100644 --- a/vuu-ui/packages/vuu-popups/src/popup-menu/PopupMenu.tsx +++ b/vuu-ui/packages/vuu-popups/src/popup-menu/PopupMenu.tsx @@ -1,3 +1,7 @@ +import { MenuActionHandler, MenuBuilder } from "@finos/vuu-data-types"; +import { useId } from "@finos/vuu-utils"; +import { Button } from "@salt-ds/core"; +import cx from "clsx"; import { HTMLAttributes, MouseEvent, @@ -5,17 +9,12 @@ import { useRef, useState, } from "react"; +import { MenuOpenHandler, useContextMenu } from "../menu"; import { - MenuOpenHandler, PopupCloseCallback, PopupCloseReason, reasonIsClickAway, - useContextMenu, -} from "@finos/vuu-popups"; -import cx from "classnames"; -import { Button } from "@salt-ds/core"; -import { useId } from "@finos/vuu-layout"; -import { MenuActionHandler, MenuBuilder } from "@finos/vuu-data-types"; +} from "../popup/popup-service"; import "./PopupMenu.css"; diff --git a/vuu-ui/packages/vuu-popups/src/popup/Popup.tsx b/vuu-ui/packages/vuu-popups/src/popup/Popup.tsx index 30450c84e..bdc250dd8 100644 --- a/vuu-ui/packages/vuu-popups/src/popup/Popup.tsx +++ b/vuu-ui/packages/vuu-popups/src/popup/Popup.tsx @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, RefObject } from "react"; import { Position, useAnchoredPosition } from "./useAnchoredPosition"; @@ -6,6 +6,7 @@ import "./Popup.css"; export type PopupPlacement = | "absolute" + | "auto" | "below" | "below-center" | "below-right" diff --git a/vuu-ui/packages/vuu-popups/src/popup/popup-service.ts b/vuu-ui/packages/vuu-popups/src/popup/popup-service.ts index 34ede5088..c1eddb349 100644 --- a/vuu-ui/packages/vuu-popups/src/popup/popup-service.ts +++ b/vuu-ui/packages/vuu-popups/src/popup/popup-service.ts @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import React, { createElement, CSSProperties, diff --git a/vuu-ui/packages/vuu-popups/src/popup/useAnchoredPosition.ts b/vuu-ui/packages/vuu-popups/src/popup/useAnchoredPosition.ts index 09d367664..a1aa0b4cb 100644 --- a/vuu-ui/packages/vuu-popups/src/popup/useAnchoredPosition.ts +++ b/vuu-ui/packages/vuu-popups/src/popup/useAnchoredPosition.ts @@ -89,7 +89,7 @@ export const useAnchoredPosition = ({ useLayoutEffect(() => { if (placement === "absolute" && positionProp) { setPosition(positionProp); - } else if (anchorElement.current) { + } else if (anchorElement.current && placement !== "auto") { const dimensions = popupRef.current === null ? undefined diff --git a/vuu-ui/packages/vuu-popups/src/portal-deprecated/render-portal.tsx b/vuu-ui/packages/vuu-popups/src/portal-deprecated/render-portal.tsx index 03389d2f3..ebae78907 100644 --- a/vuu-ui/packages/vuu-popups/src/portal-deprecated/render-portal.tsx +++ b/vuu-ui/packages/vuu-popups/src/portal-deprecated/render-portal.tsx @@ -1,6 +1,6 @@ import * as ReactDOM from "react-dom"; import { ReactElement } from "react"; -import cx from "classnames"; +import cx from "clsx"; let containerId = 1; diff --git a/vuu-ui/packages/vuu-popups/src/portal/Portal.tsx b/vuu-ui/packages/vuu-popups/src/portal/Portal.tsx index f09bd0045..55d86557b 100644 --- a/vuu-ui/packages/vuu-popups/src/portal/Portal.tsx +++ b/vuu-ui/packages/vuu-popups/src/portal/Portal.tsx @@ -1,4 +1,4 @@ -import { ThemeAttributes, useThemeAttributes } from "@finos/vuu-shell"; +import { ThemeAttributes, useThemeAttributes } from "@finos/vuu-utils"; import { ReactNode, useLayoutEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; @@ -18,9 +18,11 @@ export interface PortalProps { */ container?: Element | (() => Element | null) | null; /** - * If this node does not exist on the document, it will be created for you. + * Id of element into which portal will be rendered. If this node does not exist on the document, + * it will be created for you. If more than one value is provided, the first element found will + * be used. */ - id?: string; + id?: string | string[]; /** * Callback invoked immediately after render (in layoutEffect). Can be * used to check position vis-a-vis viewport and adjust if out of bounds @@ -42,7 +44,21 @@ function getContainer(container: PortalProps["container"]) { return typeof container === "function" ? container() : container; } -const DEFAULT_ID = "vuu-portal-root"; +const DEFAULT_ID = ["vuu-dialog-portal-root", "vuu-portal-root"]; + +const getFirstAvailableElementById = (id: string | string[]) => { + if (Array.isArray(id)) { + for (const i of id) { + const element = document.getElementById(i); + if (element) { + return element; + } + } + } else { + return document.getElementById(id); + } + return null; +}; /** * Portals provide a first-class way to render children into a DOM node @@ -63,12 +79,17 @@ export const Portal = ({ useThemeAttributes(themeAttributes); useLayoutEffect(() => { - const root = document.getElementById(id); + const root = getFirstAvailableElementById(id); if (root) { portalRef.current = root; } else { portalRef.current = document.createElement("div"); - portalRef.current.id = id; + portalRef.current.id = + typeof id === "string" + ? id + : id.length > 0 + ? (id.at(-1) as string) + : "vuu-portal-root"; } const el = portalRef.current; if (!container.contains(el)) { diff --git a/vuu-ui/packages/vuu-popups/src/prompt/Prompt.tsx b/vuu-ui/packages/vuu-popups/src/prompt/Prompt.tsx index fd2406e81..8432e8675 100644 --- a/vuu-ui/packages/vuu-popups/src/prompt/Prompt.tsx +++ b/vuu-ui/packages/vuu-popups/src/prompt/Prompt.tsx @@ -1,6 +1,6 @@ -import { useThemeAttributes } from "@finos/vuu-shell"; +import { useThemeAttributes } from "@finos/vuu-utils"; import { Button } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, useLayoutEffect, useRef } from "react"; import { PopupComponentProps, useAnchoredPosition } from "../popup"; diff --git a/vuu-ui/packages/vuu-popups/src/tooltip/Tooltip.tsx b/vuu-ui/packages/vuu-popups/src/tooltip/Tooltip.tsx index 18b3391ad..b0dbc97a3 100644 --- a/vuu-ui/packages/vuu-popups/src/tooltip/Tooltip.tsx +++ b/vuu-ui/packages/vuu-popups/src/tooltip/Tooltip.tsx @@ -1,7 +1,7 @@ import { CSSProperties, MouseEventHandler, ReactNode, RefObject } from "react"; import { Portal } from "../portal"; import { TooltipPlacement, useAnchoredPosition } from "./useAnchoredPosition"; -import cx from "classnames"; +import cx from "clsx"; import "./Tooltip.css"; diff --git a/vuu-ui/packages/vuu-popups/src/tooltip/useTooltip.ts b/vuu-ui/packages/vuu-popups/src/tooltip/useTooltip.ts index 5e4eb9617..604e817d0 100644 --- a/vuu-ui/packages/vuu-popups/src/tooltip/useTooltip.ts +++ b/vuu-ui/packages/vuu-popups/src/tooltip/useTooltip.ts @@ -1,7 +1,7 @@ +import { useId } from "@finos/vuu-utils"; import { MouseEvent, ReactNode, useCallback, useRef, useState } from "react"; import { TooltipProps } from "./Tooltip"; import { TooltipPlacement } from "./useAnchoredPosition"; -import { useId } from "@finos/vuu-layout"; export interface TooltipHookProps { id: string; diff --git a/vuu-ui/packages/vuu-protocol-types/index.d.ts b/vuu-ui/packages/vuu-protocol-types/index.d.ts index 178a104a6..1c52cc242 100644 --- a/vuu-ui/packages/vuu-protocol-types/index.d.ts +++ b/vuu-ui/packages/vuu-protocol-types/index.d.ts @@ -216,7 +216,7 @@ export interface ServerToClientRPC { export interface ServerToClientViewportRpcResponse { action: { msg?: string; - type: "VP_RCP_FAILURE" | "VP_RCP_SUCCESS"; + type: "VP_RPC_FAILURE" | "VP_RPC_SUCCESS"; }; type: "VIEW_PORT_RPC_REPONSE"; method: string; diff --git a/vuu-ui/packages/vuu-shell/package.json b/vuu-ui/packages/vuu-shell/package.json index e64a8c5a8..5ee68a7c4 100644 --- a/vuu-ui/packages/vuu-shell/package.json +++ b/vuu-ui/packages/vuu-shell/package.json @@ -10,9 +10,7 @@ "type-defs": "node ../../scripts/build-type-defs.mjs" }, "dependencies": { - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15", + "@salt-ds/core": "1.13.2", "@finos/vuu-data": "0.0.26", "@finos/vuu-icons": "0.0.26", "@finos/vuu-filters": "0.0.26", @@ -20,11 +18,12 @@ "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", - "@finos/vuu-utils": "0.0.26" + "@finos/vuu-utils": "0.0.26", + "html-to-image": "^1.11.11" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } } diff --git a/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx b/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx index 6bdb0c67f..a14067b19 100644 --- a/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx +++ b/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx @@ -1,14 +1,10 @@ -import { ColumnDescriptor, ListOption } from "@finos/vuu-table-types"; +import { DefaultColumnConfiguration, ListOption } from "@finos/vuu-table-types"; import { RpcResponseHandler } from "@finos/vuu-data-react"; import { createContext, ReactElement, ReactNode, useContext } from "react"; import { VuuTable } from "@finos/vuu-protocol-types"; export type LookupTableProvider = (table: VuuTable) => ListOption[]; -export type DefaultColumnConfiguration = ( - tableName: T, - columnName: string -) => Partial | undefined; export interface ShellContextProps { getDefaultColumnConfig?: DefaultColumnConfiguration; getLookupValues?: LookupTableProvider; diff --git a/vuu-ui/packages/vuu-shell/src/app-header/AppHeader.tsx b/vuu-ui/packages/vuu-shell/src/app-header/AppHeader.tsx index 79b59c25a..c1cb8965f 100644 --- a/vuu-ui/packages/vuu-shell/src/app-header/AppHeader.tsx +++ b/vuu-ui/packages/vuu-shell/src/app-header/AppHeader.tsx @@ -2,13 +2,13 @@ import { HTMLAttributes, useCallback } from "react"; import { VuuUser } from "../shell"; // import { UserProfile } from "../user-profile"; // import { ThemeSwitch } from "../theme-switch"; -import { ThemeMode } from "../theme-provider"; -import cx from "classnames"; import { Toolbar } from "@finos/vuu-layout"; +import { ThemeMode } from "@finos/vuu-utils"; +import cx from "clsx"; import { logout } from "../login"; -import "./AppHeader.css"; import { Button } from "@salt-ds/core"; +import "./AppHeader.css"; const classBase = "vuuAppHeader"; export interface AppHeaderProps extends HTMLAttributes { diff --git a/vuu-ui/packages/vuu-shell/src/connection-status/ConnectionStatusIcon.tsx b/vuu-ui/packages/vuu-shell/src/connection-status/ConnectionStatusIcon.tsx index 2a3456db6..2cf5c3e3c 100644 --- a/vuu-ui/packages/vuu-shell/src/connection-status/ConnectionStatusIcon.tsx +++ b/vuu-ui/packages/vuu-shell/src/connection-status/ConnectionStatusIcon.tsx @@ -1,49 +1,58 @@ -import React, { useEffect, useState } from 'react'; -import cx from 'classnames'; -import './ConnectionStatusIcon.css'; +import React, { useEffect, useState } from "react"; +import cx from "clsx"; -type connectionStatus = 'connected' | 'reconnected' | 'connecting' | 'disconnected'; +import "./ConnectionStatusIcon.css"; + +type connectionStatus = + | "connected" + | "reconnected" + | "connecting" + | "disconnected"; interface ConnectionStatusProps { - connectionStatus: connectionStatus - className?: string; - props?: unknown; - element?: string; + connectionStatus: connectionStatus; + className?: string; + props?: unknown; + element?: string; } -export const ConnectionStatusIcon = ({ connectionStatus, className, element = 'span', ...props}: ConnectionStatusProps) => { - const [classBase, setClassBase] = useState('vuuConnectingStatus'); - useEffect(() => { - switch(connectionStatus) { - case 'connected': - case 'reconnected': - setClassBase('vuuActiveStatus'); - break; - case 'connecting': - setClassBase('vuuConnectingStatus'); - break; - case 'disconnected': - setClassBase('vuuDisconnectedStatus'); - break; - default: - break; - } - }, [connectionStatus]); +export const ConnectionStatusIcon = ({ + connectionStatus, + className, + element = "span", + ...props +}: ConnectionStatusProps) => { + const [classBase, setClassBase] = useState("vuuConnectingStatus"); + useEffect(() => { + switch (connectionStatus) { + case "connected": + case "reconnected": + setClassBase("vuuActiveStatus"); + break; + case "connecting": + setClassBase("vuuConnectingStatus"); + break; + case "disconnected": + setClassBase("vuuDisconnectedStatus"); + break; + default: + break; + } + }, [connectionStatus]); - const statusIcon = React.createElement ( - element, - { - ...props, - className: cx('vuuStatus vuuIcon', classBase, className) - }, - ) + const statusIcon = React.createElement(element, { + ...props, + className: cx("vuuStatus vuuIcon", classBase, className), + }); - return ( - <> -
- {statusIcon} -
Status: {connectionStatus.toUpperCase()}
-
- - ) -} \ No newline at end of file + return ( + <> +
+ {statusIcon} +
+ Status: {connectionStatus.toUpperCase()} +
+
+ + ); +}; diff --git a/vuu-ui/packages/vuu-shell/src/density-switch/DensitySwitch.tsx b/vuu-ui/packages/vuu-shell/src/density-switch/DensitySwitch.tsx deleted file mode 100644 index 03cd00263..000000000 --- a/vuu-ui/packages/vuu-shell/src/density-switch/DensitySwitch.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Dropdown } from "@salt-ds/lab"; -import { Density } from "@salt-ds/core"; -import { HTMLAttributes, useCallback } from "react"; -import cx from "classnames"; - -const classBase = "vuuDensitySwitch"; - -const densities: Density[] = ["high", "medium", "low", "touch"]; -const DEFAULT_DENSITY = "high"; - -export interface DensitySwitchProps - extends Omit, "onChange"> { - defaultDensity?: Density; - density?: Density; - onChange: (density: Density) => void; -} - -export const DensitySwitch = ({ - className: classNameProp, - defaultDensity = DEFAULT_DENSITY, - onChange, -}: DensitySwitchProps) => { - const handleSelectionChange = useCallback( - (_event, selectedItem) => { - onChange(selectedItem); - }, - [onChange] - ); - - const className = cx(classBase, classNameProp); - - return ( - - className={className} - source={densities} - defaultSelected={defaultDensity} - onSelectionChange={handleSelectionChange} - /> - ); -}; diff --git a/vuu-ui/packages/vuu-shell/src/density-switch/index.ts b/vuu-ui/packages/vuu-shell/src/density-switch/index.ts deleted file mode 100644 index 239aae884..000000000 --- a/vuu-ui/packages/vuu-shell/src/density-switch/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./DensitySwitch" \ No newline at end of file diff --git a/vuu-ui/packages/vuu-shell/src/index.ts b/vuu-ui/packages/vuu-shell/src/index.ts index 954fed7b5..2a67d7fee 100644 --- a/vuu-ui/packages/vuu-shell/src/index.ts +++ b/vuu-ui/packages/vuu-shell/src/index.ts @@ -1,6 +1,5 @@ export * from "./app-header"; export * from "./connection-status"; -export * from "./density-switch"; export * from "./feature"; export * from "./layout-management"; export * from "./left-nav"; @@ -10,6 +9,5 @@ export * from "./shell"; export * from "./shell-layouts"; export * from "./shellTypes"; export * from "./ShellContextProvider"; -export * from "./theme-provider"; export * from "./feature-list"; export * from "./theme-switch"; diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx index 82721ccd5..fdd926dd6 100644 --- a/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx +++ b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx @@ -2,6 +2,7 @@ import { HTMLAttributes } from "react"; import { List } from "@finos/vuu-ui-controls"; import { LayoutMetadata } from "./layoutTypes"; import { useLayoutManager } from "./useLayoutManager"; +import { LayoutTile } from "./LayoutTile"; import "./LayoutList.css"; @@ -11,7 +12,7 @@ type LayoutGroups = { const classBase = "vuuLayoutList"; -export const LayoutsList = (props: HTMLAttributes) => { +export const LayoutList = (props: HTMLAttributes) => { const { layoutMetadata, loadLayoutById } = useLayoutManager(); const handleLoadLayout = (layoutId?: string) => { @@ -34,7 +35,12 @@ export const LayoutsList = (props: HTMLAttributes) => { }, {}); return ( -
+
My Layouts
height="auto" @@ -43,29 +49,16 @@ export const LayoutsList = (props: HTMLAttributes) => { if (!item) return <>; const [groupName, layoutMetadata] = item; return ( - <> +
{groupName}
{layoutMetadata.map((metadata) => ( -
handleLoadLayout(metadata?.id)} - > - -
-
- {metadata?.name} -
-
-
{`${metadata?.user}, ${metadata?.created}`}
-
-
-
+ ))} - +
); }} /> diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/LayoutTile.css b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutTile.css new file mode 100644 index 000000000..7f77107fc --- /dev/null +++ b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutTile.css @@ -0,0 +1,28 @@ +.vuuLayoutTile-layoutTile { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 0px; + flex: 1 1 auto; + cursor: pointer; +} + +.vuuLayoutTile-layoutName { + color: var(--light-text-primary, #15171B); + font-weight: 600; + line-height: 133.333%; + text-transform: capitalize; +} + +.vuuLayoutTile-screenshot { + width: 60px; + height: 45.6px; + border: 1px solid #D6D7DA; +} + +.vuuLayoutTile-layoutDetails { + color: var(--light-text-secondary, #606477); + font-size: 10px; + font-weight: 600; + line-height: 150%; +} diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/LayoutTile.tsx b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutTile.tsx new file mode 100644 index 000000000..7311b3410 --- /dev/null +++ b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutTile.tsx @@ -0,0 +1,33 @@ +import { LayoutMetadata } from "./layoutTypes"; + +import "./LayoutTile.css"; + +const classBase = "vuuLayoutTile"; + +type LayoutTileProps = { + metadata: LayoutMetadata; + handleLoadLayout: (layoutId?: string) => void; +}; + +export const LayoutTile = (props: LayoutTileProps) => { + const { metadata, handleLoadLayout } = props; + + return ( +
+
handleLoadLayout(metadata?.id)} + > + +
+
{metadata?.name}
+
+
{`${metadata?.user}, ${metadata?.created}`}
+
+
+
+
+ ); +}; diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.css b/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.css index f7c7a3fde..ec315b1ac 100644 --- a/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.css +++ b/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.css @@ -9,6 +9,12 @@ --saltText-color: var(--text-secondary-foreground, #606477); } +.spinner{ + width: 100px; + height:100px; + background-image: var(--svg-spinner); +} + .saveLayoutPanel-panelContainer { display: flex; flex-direction: column; @@ -69,13 +75,9 @@ } .saveLayoutPanel-screenshot { - display: flex; - justify-content: center; - align-items: center; background: lightgray 50% / cover no-repeat; width: 273px; height: 186px; - flex-shrink: 0; } .saveLayoutPanel-buttonsContainer { diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.tsx b/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.tsx index a86abd873..f8817823c 100644 --- a/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.tsx +++ b/vuu-ui/packages/vuu-shell/src/layout-management/SaveLayoutPanel.tsx @@ -1,8 +1,9 @@ -import { ChangeEvent, useEffect, useState } from "react"; -import { Input, Button, FormField, FormFieldLabel, Text } from "@salt-ds/core"; -import { ComboBox, Checkbox, RadioButton } from "@finos/vuu-ui-controls"; -import { takeScreenshot } from "@finos/vuu-utils"; +import { Checkbox, ComboBox, RadioButton } from "@finos/vuu-ui-controls"; +import { takeScreenshot } from "./screenshot-utils"; +import { Button, FormField, FormFieldLabel, Input, Text } from "@salt-ds/core"; +import { ChangeEvent, useEffect, useMemo, useState } from "react"; import { LayoutMetadataDto } from "./layoutTypes"; +import { getAuthDetailsFromCookies } from "../login"; import "./SaveLayoutPanel.css"; @@ -32,12 +33,20 @@ export const SaveLayoutPanel = (props: SaveLayoutPanelProps) => { const [checkValues, setCheckValues] = useState([]); const [radioValue, setRadioValue] = useState(radioValues[0]); const [screenshot, setScreenshot] = useState(); + const [screenshotErrorMessage, setScreenshotErrorMessage] = useState< + string | undefined + >(); + const [username] = getAuthDetailsFromCookies(); useEffect(() => { if (componentId) { - takeScreenshot(document.getElementById(componentId) as HTMLElement).then( - (screenshot) => setScreenshot(screenshot) - ); + takeScreenshot(document.getElementById(componentId) as HTMLElement) + .then((screenshot) => { + setScreenshot(screenshot); + }) + .catch((error: Error) => { + setScreenshotErrorMessage(error.message); + }); } }, [componentId]); @@ -46,10 +55,26 @@ export const SaveLayoutPanel = (props: SaveLayoutPanelProps) => { name: layoutName, group, screenshot: screenshot ?? "", - user: "User", + user: username, }); }; + const screenshotContent = useMemo(() => { + if (screenshot) { + return ( + screenshot of current layout + ); + } + if (screenshotErrorMessage) { + return {screenshotErrorMessage}; + } + return
; + }, [screenshot, screenshotErrorMessage]); + return (
@@ -119,15 +144,7 @@ export const SaveLayoutPanel = (props: SaveLayoutPanelProps) => {
- {screenshot ? ( - screenshot of current layout - ) : ( - No screenshot available - )} + {screenshotContent}
diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/screenshot-utils.ts b/vuu-ui/packages/vuu-shell/src/layout-management/screenshot-utils.ts new file mode 100644 index 000000000..144e4ac3c --- /dev/null +++ b/vuu-ui/packages/vuu-shell/src/layout-management/screenshot-utils.ts @@ -0,0 +1,31 @@ +import { toPng } from "html-to-image"; + +/** + * Takes a screenshot of the given node and returns the base64 encoded image url + * @param node HTMLElement to take screenshot of + * @returns Base64 encoded image url + */ +export const takeScreenshot = (node: HTMLElement): Promise => { + return new Promise((resolve, reject) => { + toPng(node, { + cacheBust: true /*, + filter: (child) => + // remove content of table rows + child.nodeType === Node.TEXT_NODE || + child.getAttribute("role") !== "row",*/, + }) + .then((screenshot) => { + if (!screenshot) { + reject(new Error("No Screenshot available")); + } + resolve(screenshot); + }) + .catch((error: Error) => { + console.error( + "the following error occurred while taking a screenshot of a DOMNode", + error + ); + reject(new Error("Error taking screenshot")); + }); + }); +}; diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx b/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx index 178795ce8..8b371efdb 100644 --- a/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx +++ b/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx @@ -8,25 +8,27 @@ import React, { import { ApplicationJSON, ApplicationSettings, - loadingApplicationJson, LayoutJSON, - LayoutPersistenceManager, - LocalLayoutPersistenceManager, - RemoteLayoutPersistenceManager, resolveJSONPath, - defaultApplicationJson, ApplicationSetting, } from "@finos/vuu-layout"; import { NotificationLevel, useNotifications } from "@finos/vuu-popups"; import { LayoutMetadata, LayoutMetadataDto } from "./layoutTypes"; +import { + defaultApplicationJson, + PersistenceManager, + loadingApplicationJson, + LocalPersistenceManager, + RemotePersistenceManager, +} from "../persistence-management"; -let _persistenceManager: LayoutPersistenceManager; +let _persistenceManager: PersistenceManager; const getPersistenceManager = () => { if (_persistenceManager === undefined) { _persistenceManager = process.env.LOCAL - ? new LocalLayoutPersistenceManager() - : new RemoteLayoutPersistenceManager(); + ? new LocalPersistenceManager() + : new RemotePersistenceManager(); } return _persistenceManager; }; @@ -237,7 +239,7 @@ export const LayoutManagementProvider = ( getPersistenceManager() .loadLayout(id) .then((layoutJson) => { - const { layout: currentLayout } = applicationJSONRef.current; + const { layout: currentLayout } = applicationJSONRef.current; setApplicationLayout({ ...currentLayout, children: (currentLayout.children || []).concat(layoutJson), diff --git a/vuu-ui/packages/vuu-shell/src/left-nav/LeftNav.tsx b/vuu-ui/packages/vuu-shell/src/left-nav/LeftNav.tsx index d6ca3515b..6f36ed978 100644 --- a/vuu-ui/packages/vuu-shell/src/left-nav/LeftNav.tsx +++ b/vuu-ui/packages/vuu-shell/src/left-nav/LeftNav.tsx @@ -2,12 +2,12 @@ import { VuuLogo } from "@finos/vuu-icons"; import { Stack, useLayoutProviderDispatch } from "@finos/vuu-layout"; import { LayoutResizeAction } from "@finos/vuu-layout/src/layout-reducer"; import { Tab, Tabstrip } from "@finos/vuu-ui-controls"; -import cx from "classnames"; -import { LayoutsList } from "../layout-management"; +import { useThemeAttributes } from "@finos/vuu-utils"; +import cx from "clsx"; import { CSSProperties, HTMLAttributes, useCallback, useState } from "react"; import { FeatureProps } from "../feature"; import { FeatureList } from "../feature-list"; -import { useThemeAttributes } from "../theme-provider"; +import { LayoutList } from "../layout-management"; import "./LeftNav.css"; @@ -182,7 +182,7 @@ export const LeftNav = (props: LeftNavProps) => {
- +
diff --git a/vuu-ui/packages/vuu-shell/src/login/LoginPanel.tsx b/vuu-ui/packages/vuu-shell/src/login/LoginPanel.tsx index b01ffacfa..b78a0800e 100644 --- a/vuu-ui/packages/vuu-shell/src/login/LoginPanel.tsx +++ b/vuu-ui/packages/vuu-shell/src/login/LoginPanel.tsx @@ -9,7 +9,7 @@ import { import { Button, FormField, FormFieldLabel } from "@salt-ds/core"; import { VuuInput } from "@finos/vuu-ui-controls"; import { VuuLogo } from "./VuuLogo"; -import cx from "classnames"; +import cx from "clsx"; import "./LoginPanel.css"; diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/LocalLayoutPersistenceManager.ts b/vuu-ui/packages/vuu-shell/src/persistence-management/LocalPersistenceManager.ts similarity index 80% rename from vuu-ui/packages/vuu-layout/src/layout-persistence/LocalLayoutPersistenceManager.ts rename to vuu-ui/packages/vuu-shell/src/persistence-management/LocalPersistenceManager.ts index 929c70058..56648dffe 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/LocalLayoutPersistenceManager.ts +++ b/vuu-ui/packages/vuu-shell/src/persistence-management/LocalPersistenceManager.ts @@ -1,29 +1,32 @@ +import { ApplicationJSON, LayoutJSON } from "@finos/vuu-layout"; +import { getLocalEntity, saveLocalEntity } from "@finos/vuu-filters"; +import { getAuthDetailsFromCookies } from "@finos/vuu-shell"; +import { formatDate, getUniqueId } from "@finos/vuu-utils"; + +import { defaultApplicationJson } from "./defaultApplicationJson"; +import { PersistenceManager } from "./PersistenceManager"; import { Layout, LayoutMetadata, LayoutMetadataDto, WithId, -} from "@finos/vuu-shell"; -import { - ApplicationJSON, - LayoutJSON, - LayoutPersistenceManager, -} from "@finos/vuu-layout"; -import { getLocalEntity, saveLocalEntity } from "@finos/vuu-filters"; -import { formatDate, getUniqueId } from "@finos/vuu-utils"; +} from "../layout-management"; -import { defaultApplicationJson } from "./defaultApplicationJson"; +const baseMetadataSaveLocation = "layouts/metadata"; +const baseLayoutsSaveLocation = "layouts/layouts"; -const metadataSaveLocation = "layouts/metadata"; -const layoutsSaveLocation = "layouts/layouts"; +export class LocalPersistenceManager implements PersistenceManager { + username: string = getAuthDetailsFromCookies()[0]; + metadataSaveLocation = `${baseMetadataSaveLocation}/${this.username}`; + layoutsSaveLocation = `${baseLayoutsSaveLocation}/${this.username}`; -export class LocalLayoutPersistenceManager implements LayoutPersistenceManager { - #urlKey = "api/vui"; + #urlKey = `api/vui/${this.username}`; constructor(urlKey?: string) { if (urlKey) { this.#urlKey = urlKey; } } + createLayout( metadata: LayoutMetadataDto, layout: LayoutJSON @@ -35,7 +38,7 @@ export class LocalLayoutPersistenceManager implements LayoutPersistenceManager { const newMetadata: LayoutMetadata = { ...metadata, id, - created: formatDate("dd.mm.yyyy")(new Date()), + created: formatDate({ date: "dd.mm.yyyy" })(new Date()), }; this.saveLayoutsWithMetadata( @@ -106,7 +109,7 @@ export class LocalLayoutPersistenceManager implements LayoutPersistenceManager { loadMetadata(): Promise { return new Promise((resolve) => { - const metadata = getLocalEntity(metadataSaveLocation); + const metadata = getLocalEntity(this.metadataSaveLocation); resolve(metadata || []); }); } @@ -136,24 +139,24 @@ export class LocalLayoutPersistenceManager implements LayoutPersistenceManager { }); } - private loadLayouts(): Promise { + loadLayouts = (): Promise => { return new Promise((resolve) => { - const layouts = getLocalEntity(layoutsSaveLocation); + const layouts = getLocalEntity(this.layoutsSaveLocation); resolve(layouts || []); }); } - private saveLayoutsWithMetadata( + saveLayoutsWithMetadata = ( layouts: Layout[], metadata: LayoutMetadata[] - ): void { - saveLocalEntity(layoutsSaveLocation, layouts); - saveLocalEntity(metadataSaveLocation, metadata); + ): void => { + saveLocalEntity(this.layoutsSaveLocation, layouts); + saveLocalEntity(this.metadataSaveLocation, metadata); } // Ensures that there is exactly one Layout entry and exactly one Metadata // entry in local storage corresponding to the provided ID. - private async validateIds(id: string): Promise { + validateIds = async (id: string): Promise => { return Promise.all([ this.validateId(id, "metadata").catch((error) => error.message), this.validateId(id, "layout").catch((error) => error.message), @@ -171,13 +174,13 @@ export class LocalLayoutPersistenceManager implements LayoutPersistenceManager { // Ensures that there is exactly one element (Layout or Metadata) in local // storage corresponding to the provided ID. - private validateId( + validateId = ( id: string, dataType: "metadata" | "layout" - ): Promise { + ): Promise => { return new Promise((resolve, reject) => { const loadFunc = - dataType === "metadata" ? this.loadMetadata : this.loadLayouts; + dataType === "metadata" ? () => this.loadMetadata() : () => this.loadLayouts(); loadFunc().then((array: WithId[]) => { const count = array.filter((element) => element.id === id).length; diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/LayoutPersistenceManager.ts b/vuu-ui/packages/vuu-shell/src/persistence-management/PersistenceManager.ts similarity index 94% rename from vuu-ui/packages/vuu-layout/src/layout-persistence/LayoutPersistenceManager.ts rename to vuu-ui/packages/vuu-shell/src/persistence-management/PersistenceManager.ts index 3ac7c097d..83c1d5921 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/LayoutPersistenceManager.ts +++ b/vuu-ui/packages/vuu-shell/src/persistence-management/PersistenceManager.ts @@ -1,7 +1,7 @@ import { ApplicationJSON, LayoutJSON } from "@finos/vuu-layout"; -import { LayoutMetadata, LayoutMetadataDto } from "@finos/vuu-shell"; +import { LayoutMetadata, LayoutMetadataDto } from "../layout-management"; -export interface LayoutPersistenceManager { +export interface PersistenceManager { /** * Saves a new layout and its corresponding metadata * diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/RemoteLayoutPersistenceManager.ts b/vuu-ui/packages/vuu-shell/src/persistence-management/RemotePersistenceManager.ts similarity index 91% rename from vuu-ui/packages/vuu-layout/src/layout-persistence/RemoteLayoutPersistenceManager.ts rename to vuu-ui/packages/vuu-shell/src/persistence-management/RemotePersistenceManager.ts index 18b6da4ee..e7c908dd3 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/RemoteLayoutPersistenceManager.ts +++ b/vuu-ui/packages/vuu-shell/src/persistence-management/RemotePersistenceManager.ts @@ -1,6 +1,10 @@ -import { LayoutMetadata, LayoutMetadataDto } from "@finos/vuu-shell"; -import { LayoutPersistenceManager } from "./LayoutPersistenceManager"; -import { ApplicationJSON, LayoutJSON } from "../layout-reducer"; +import { getAuthDetailsFromCookies } from "@finos/vuu-shell"; +import { PersistenceManager } from "./PersistenceManager"; +import { + ApplicationJSON, + LayoutJSON, +} from "@finos/vuu-layout/src/layout-reducer"; +import { LayoutMetadata, LayoutMetadataDto } from "../layout-management"; const baseURL = process.env.LAYOUT_BASE_URL; const metadataSaveLocation = "layouts/metadata"; @@ -11,9 +15,9 @@ export type CreateLayoutResponseDto = { metadata: LayoutMetadata }; export type GetLayoutResponseDto = { definition: LayoutJSON }; export type GetApplicationResponseDto = { definition: ApplicationJSON }; -export class RemoteLayoutPersistenceManager - implements LayoutPersistenceManager -{ +export class RemotePersistenceManager implements PersistenceManager { + username: string = getAuthDetailsFromCookies()[0]; + createLayout( metadata: LayoutMetadataDto, layout: LayoutJSON @@ -138,7 +142,7 @@ export class RemoteLayoutPersistenceManager method: "PUT", headers: { "Content-Type": "application/json", - username: "vuu-user", + username: this.username, }, body: JSON.stringify(applicationJSON), }) @@ -159,7 +163,7 @@ export class RemoteLayoutPersistenceManager fetch(`${baseURL}/${applicationLayoutsSaveLocation}`, { method: "GET", headers: { - username: "vuu-user", + username: this.username, }, }) .then((response) => { diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/defaultApplicationJson.ts b/vuu-ui/packages/vuu-shell/src/persistence-management/defaultApplicationJson.ts similarity index 94% rename from vuu-ui/packages/vuu-layout/src/layout-persistence/defaultApplicationJson.ts rename to vuu-ui/packages/vuu-shell/src/persistence-management/defaultApplicationJson.ts index a8e805109..ba3b475a3 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/defaultApplicationJson.ts +++ b/vuu-ui/packages/vuu-shell/src/persistence-management/defaultApplicationJson.ts @@ -1,4 +1,4 @@ -import { ApplicationJSON, LayoutJSON } from "../layout-reducer"; +import { ApplicationJSON, LayoutJSON } from "@finos/vuu-layout"; export const warningLayout: LayoutJSON = { type: "View", diff --git a/vuu-ui/packages/vuu-shell/src/persistence-management/index.ts b/vuu-ui/packages/vuu-shell/src/persistence-management/index.ts new file mode 100644 index 000000000..53d202da6 --- /dev/null +++ b/vuu-ui/packages/vuu-shell/src/persistence-management/index.ts @@ -0,0 +1,5 @@ +export * from "./defaultApplicationJson"; +export * from "./PersistenceManager"; +export * from "./LocalPersistenceManager"; +export * from "./RemotePersistenceManager"; +export * from "./useLayoutContextMenuItems"; diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/useLayoutContextMenuItems.tsx b/vuu-ui/packages/vuu-shell/src/persistence-management/useLayoutContextMenuItems.tsx similarity index 98% rename from vuu-ui/packages/vuu-layout/src/layout-persistence/useLayoutContextMenuItems.tsx rename to vuu-ui/packages/vuu-shell/src/persistence-management/useLayoutContextMenuItems.tsx index b2cc99407..ec3349e5e 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/useLayoutContextMenuItems.tsx +++ b/vuu-ui/packages/vuu-shell/src/persistence-management/useLayoutContextMenuItems.tsx @@ -1,8 +1,3 @@ -import { - LayoutMetadataDto, - SaveLayoutPanel, - useLayoutManager, -} from "@finos/vuu-shell"; import { ContextMenuItemDescriptor, MenuActionHandler, @@ -10,6 +5,11 @@ import { } from "@finos/vuu-data-types"; import { useCallback, useMemo } from "react"; import { MenuActionClosePopup, SetDialog } from "@finos/vuu-popups"; +import { + LayoutMetadataDto, + SaveLayoutPanel, + useLayoutManager, +} from "../layout-management"; export const useLayoutContextMenuItems = (setDialogState: SetDialog) => { const { saveLayout } = useLayoutManager(); diff --git a/vuu-ui/packages/vuu-shell/src/session-editing-form/SessionEditingForm.tsx b/vuu-ui/packages/vuu-shell/src/session-editing-form/SessionEditingForm.tsx index 79dde1378..73638b30e 100644 --- a/vuu-ui/packages/vuu-shell/src/session-editing-form/SessionEditingForm.tsx +++ b/vuu-ui/packages/vuu-shell/src/session-editing-form/SessionEditingForm.tsx @@ -1,3 +1,19 @@ +import { VuuDataSource } from "@finos/vuu-data-remote"; +import { DataSource, TableSchema } from "@finos/vuu-data-types"; +import { + VuuColumnDataType, + VuuDataRow, + VuuRowDataItemType, +} from "@finos/vuu-protocol-types"; +import { + buildColumnMap, + hasAction, + isErrorResponse, + isValidNumber, + shallowEquals, +} from "@finos/vuu-utils"; +import { Button, useIdMemo } from "@salt-ds/core"; +import cx from "clsx"; import { ChangeEvent, FocusEvent, @@ -8,22 +24,6 @@ import { useRef, useState, } from "react"; -import cx from "classnames"; -import { - VuuColumnDataType, - VuuDataRow, - VuuRowDataItemType, -} from "@finos/vuu-protocol-types"; -import { useIdMemo } from "@salt-ds/core"; -import { Button } from "@salt-ds/core"; -import { - DataSource, - hasAction, - isErrorResponse, - RemoteDataSource, - TableSchema, -} from "@finos/vuu-data"; -import { buildColumnMap, isValidNumber, shallowEquals } from "@finos/vuu-utils"; import "./SessionEditingForm.css"; @@ -135,7 +135,7 @@ const getDataSource = ( if (dataSource) { return dataSource; } else if (schema) { - return new RemoteDataSource({ + return new VuuDataSource({ bufferSize: 0, table: schema.table, columns: schema.columns.map((col) => col.name), diff --git a/vuu-ui/packages/vuu-shell/src/shell-layouts/context-panel/ContextPanel.tsx b/vuu-ui/packages/vuu-shell/src/shell-layouts/context-panel/ContextPanel.tsx index c341013b9..89ca7cff7 100644 --- a/vuu-ui/packages/vuu-shell/src/shell-layouts/context-panel/ContextPanel.tsx +++ b/vuu-ui/packages/vuu-shell/src/shell-layouts/context-panel/ContextPanel.tsx @@ -1,5 +1,5 @@ import { Button } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { useCallback, useMemo } from "react"; import { layoutFromJson, diff --git a/vuu-ui/packages/vuu-shell/src/shell-layouts/side-panel/SidePanel.tsx b/vuu-ui/packages/vuu-shell/src/shell-layouts/side-panel/SidePanel.tsx index 4bd61099c..4ffa9cd1d 100644 --- a/vuu-ui/packages/vuu-shell/src/shell-layouts/side-panel/SidePanel.tsx +++ b/vuu-ui/packages/vuu-shell/src/shell-layouts/side-panel/SidePanel.tsx @@ -1,5 +1,5 @@ import { CSSProperties, HTMLAttributes, useMemo } from "react"; -import cx from "classnames"; +import cx from "clsx"; import "./SidePanel.css"; // import { useLayoutManager } from "../../layout-management"; diff --git a/vuu-ui/packages/vuu-shell/src/shell.tsx b/vuu-ui/packages/vuu-shell/src/shell.tsx index d9d298dd8..c1502432b 100644 --- a/vuu-ui/packages/vuu-shell/src/shell.tsx +++ b/vuu-ui/packages/vuu-shell/src/shell.tsx @@ -1,17 +1,20 @@ -import { connectToServer } from "@finos/vuu-data"; +import { connectToServer } from "@finos/vuu-data-remote"; import { DraggableLayout, LayoutProvider, LayoutProviderProps, - loadingApplicationJson, - useLayoutContextMenuItems, + StackLayout, } from "@finos/vuu-layout"; import { LayoutChangeHandler } from "@finos/vuu-layout/src/layout-reducer"; -import { logger } from "@finos/vuu-utils"; -import cx from "classnames"; +import { + logger, + ThemeMode, + ThemeProvider, + useThemeAttributes, +} from "@finos/vuu-utils"; +import cx from "clsx"; import { HTMLAttributes, - ReactElement, ReactNode, useCallback, useEffect, @@ -21,11 +24,19 @@ import { AppHeader } from "./app-header"; import { useLayoutManager } from "./layout-management"; import { SidePanelProps, useShellLayout } from "./shell-layouts"; import { SaveLocation } from "./shellTypes"; -import { ThemeMode, ThemeProvider, useThemeAttributes } from "./theme-provider"; -import { ShellContextProvider } from "."; import { ContextMenuProvider, useDialog } from "@finos/vuu-popups"; import "./shell.css"; +import { + loadingApplicationJson, + useLayoutContextMenuItems, +} from "./persistence-management"; + +if (typeof StackLayout !== "function") { + console.warn( + "StackLayout module not loaded, will be unsbale to deserialize from layout JSON" + ); +} export type VuuUser = { username: string; @@ -76,7 +87,7 @@ export const Shell = ({ useLayoutContextMenuItems(setDialogState); const handleLayoutChange = useCallback( - (layout, layoutChangeReason) => { + (layout) => { try { saveApplicationLayout(layout); } catch { diff --git a/vuu-ui/packages/vuu-shell/src/shellTypes.ts b/vuu-ui/packages/vuu-shell/src/shellTypes.ts index 6a088455d..ef5cc33f8 100644 --- a/vuu-ui/packages/vuu-shell/src/shellTypes.ts +++ b/vuu-ui/packages/vuu-shell/src/shellTypes.ts @@ -1,4 +1,5 @@ -import { VuuTable } from "@finos/vuu-protocol-types"; +import type { VuuTable } from "@finos/vuu-protocol-types"; +import type { ViewProps } from "@finos/vuu-layout"; declare global { const vuuConfig: Promise; @@ -15,6 +16,7 @@ export interface FeatureConfig { featureProps?: { schema?: "*" | VuuTable; schemas?: VuuTable[]; + ViewProps?: Partial; }; } diff --git a/vuu-ui/packages/vuu-shell/src/theme-provider/index.ts b/vuu-ui/packages/vuu-shell/src/theme-provider/index.ts deleted file mode 100644 index 12243cf10..000000000 --- a/vuu-ui/packages/vuu-shell/src/theme-provider/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./ThemeProvider"; \ No newline at end of file diff --git a/vuu-ui/packages/vuu-shell/src/theme-switch/ThemeSwitch.tsx b/vuu-ui/packages/vuu-shell/src/theme-switch/ThemeSwitch.tsx index 763936b99..0d4ea5fc3 100644 --- a/vuu-ui/packages/vuu-shell/src/theme-switch/ThemeSwitch.tsx +++ b/vuu-ui/packages/vuu-shell/src/theme-switch/ThemeSwitch.tsx @@ -1,7 +1,7 @@ -import cx from "classnames"; +import cx from "clsx"; import { ToggleButton, ToggleButtonGroup, useControlled } from "@salt-ds/core"; import { HTMLAttributes, SyntheticEvent, useCallback } from "react"; -import { ThemeMode } from "../theme-provider"; +import { ThemeMode } from "@finos/vuu-utils"; import "./ThemeSwitch.css"; diff --git a/vuu-ui/packages/vuu-shell/src/user-profile/UserPanel.css b/vuu-ui/packages/vuu-shell/src/user-profile/UserPanel.css deleted file mode 100644 index 15c36f732..000000000 --- a/vuu-ui/packages/vuu-shell/src/user-profile/UserPanel.css +++ /dev/null @@ -1,26 +0,0 @@ -.vuuUserPanel { - background-color: white; - display: flex; - flex-direction: column; - max-height: 400px; - padding: 12px; -} - -vuuUserPanel-history { - flex: 1 1 auto; -} - -.vuuUserPanel-buttonBar { - --saltButton-width: 100%; - align-items: flex-end; - border-top: 1px solid var(--surface3); - display: flex; - flex: 0 0 32px; - justify-content: flex-start; -} - -.btn-logout { - --hwButton-icon-left: 12px; - --hwButton-padding: 0 6px 0 24px; - padding-left: 24px; -} diff --git a/vuu-ui/packages/vuu-shell/src/user-profile/UserPanel.tsx b/vuu-ui/packages/vuu-shell/src/user-profile/UserPanel.tsx deleted file mode 100644 index 4b2d8fa22..000000000 --- a/vuu-ui/packages/vuu-shell/src/user-profile/UserPanel.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { formatDate } from "@finos/vuu-utils"; -import { List, ListItem, ListItemProps } from "@salt-ds/lab"; -import { Button } from "@salt-ds/core"; -import { ExportIcon } from "@salt-ds/icons"; -import { - ForwardedRef, - forwardRef, - HTMLAttributes, - useCallback, - useEffect, - useState, -} from "react"; -import { getLayoutHistory, LayoutHistoryItem } from "../get-layout-history"; -import { logout } from "../login"; -import { VuuUser } from "../shell"; - -import "./UserPanel.css"; - -const byLastUpdate = ( - { lastUpdate: l1 }: LayoutHistoryItem, - { lastUpdate: l2 }: LayoutHistoryItem -) => { - return l2 === l1 ? 0 : l2 < l1 ? -1 : 1; -}; - -type HistoryEntry = { - id: string; - label: string; - lastUpdate: number; -}; - -const HistoryListItem = (props: ListItemProps) => { - return ; -}; - -export interface UserPanelProps extends HTMLAttributes { - loginUrl?: string; - onNavigate: (id: string) => void; - user: VuuUser; - layoutId: string; -} - -export const UserPanel = forwardRef(function UserPanel( - { loginUrl, onNavigate, user, layoutId = "latest" }: UserPanelProps, - forwardedRef: ForwardedRef -) { - const [history, setHistory] = useState([]); - - useEffect(() => { - async function getHistory() { - const history = await getLayoutHistory(user); - const sortedHistory = history - .filter((item) => item.id !== "latest") - .sort(byLastUpdate) - .map(({ id, lastUpdate }) => ({ - lastUpdate, - id, - label: `Saved at ${formatDate("hh:mm:ss")(new Date(lastUpdate))}`, - })); - console.log({ sortedHistory }); - setHistory(sortedHistory); - } - - getHistory(); - }, [user]); - - const handleHisorySelected = useCallback( - (evt, selected) => { - if (selected) { - onNavigate(selected.id); - } - }, - [onNavigate] - ); - - const handleLogout = useCallback(() => { - logout(loginUrl); - }, [loginUrl]); - - const selected = - history.length === 0 - ? null - : layoutId === "latest" - ? history[0] - : history.find((i) => i.id === layoutId); - - return ( -
- - ListItem={HistoryListItem} - className="vuuUserPanel-history" - onSelect={handleHisorySelected} - selected={selected} - source={history} - /> -
- -
-
- ); -}); diff --git a/vuu-ui/packages/vuu-shell/src/user-profile/UserProfile.css b/vuu-ui/packages/vuu-shell/src/user-profile/UserProfile.css deleted file mode 100644 index 1d2e0eb9a..000000000 --- a/vuu-ui/packages/vuu-shell/src/user-profile/UserProfile.css +++ /dev/null @@ -1,3 +0,0 @@ -.vuuUserProfile { - --svg-icon: var(--svg-user); -} diff --git a/vuu-ui/packages/vuu-shell/src/user-profile/UserProfile.tsx b/vuu-ui/packages/vuu-shell/src/user-profile/UserProfile.tsx deleted file mode 100644 index 32775e278..000000000 --- a/vuu-ui/packages/vuu-shell/src/user-profile/UserProfile.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Button } from "@salt-ds/core"; -import { DropdownBase } from "@salt-ds/lab"; -import { UserSolidIcon } from "@salt-ds/icons"; -import { UserPanel } from "./UserPanel"; - -import "./UserProfile.css"; -import { VuuUser } from "../shell"; - -export interface UserProfileProps { - layoutId: string; - loginUrl?: string; - onNavigate: (id: string) => void; - user: VuuUser; -} - -export const UserProfile = ({ - layoutId, - loginUrl, - onNavigate, - user, -}: UserProfileProps) => { - const handleNavigate = (id: string) => { - onNavigate(id); - }; - - return ( - - - - - ); -}; diff --git a/vuu-ui/packages/vuu-shell/src/user-profile/index.ts b/vuu-ui/packages/vuu-shell/src/user-profile/index.ts deleted file mode 100644 index 884472841..000000000 --- a/vuu-ui/packages/vuu-shell/src/user-profile/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './UserProfile'; diff --git a/vuu-ui/packages/vuu-layout/test/layout-persistence/LocalLayoutPersistenceManager.test.ts b/vuu-ui/packages/vuu-shell/test/layout-persistence/LocalLayoutPersistenceManager.test.ts similarity index 95% rename from vuu-ui/packages/vuu-layout/test/layout-persistence/LocalLayoutPersistenceManager.test.ts rename to vuu-ui/packages/vuu-shell/test/layout-persistence/LocalLayoutPersistenceManager.test.ts index 4a36e1cc8..01ad5d40a 100644 --- a/vuu-ui/packages/vuu-layout/test/layout-persistence/LocalLayoutPersistenceManager.test.ts +++ b/vuu-ui/packages/vuu-shell/test/layout-persistence/LocalLayoutPersistenceManager.test.ts @@ -1,14 +1,14 @@ -import "../global-mocks"; +import "@finos/vuu-layout/test/global-mocks"; import { Layout, LayoutMetadata, LayoutMetadataDto } from "@finos/vuu-shell"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { LocalLayoutPersistenceManager } from "../../src/layout-persistence"; -import { LayoutJSON } from "../../src/layout-reducer"; +import { LayoutJSON } from "@finos/vuu-layout"; import { getLocalEntity, saveLocalEntity, } from "../../../vuu-filters/src/local-config"; import { formatDate } from "@finos/vuu-utils"; -import { expectPromiseRejectsWithError } from "./utils"; +import { expectPromiseRejectsWithError } from "@finos/vuu-utils/test/utils"; +import { LocalPersistenceManager } from "../../src/persistence-management/LocalPersistenceManager"; vi.mock("@finos/vuu-filters", async () => { return { @@ -27,18 +27,28 @@ vi.mock("@finos/vuu-filters", async () => { }; }); -const persistenceManager = new LocalLayoutPersistenceManager(); +const username = "vuu user"; + +vi.mock("@finos/vuu-shell", async () => { + return { + getAuthDetailsFromCookies: (): [string, string] => { + return [username, "token"]; + }, + }; +}); + +const persistenceManager = new LocalPersistenceManager(); const existingId = "existing_id"; -const newDate = formatDate("dd.mm.yyyy")(new Date()); +const newDate = formatDate({ date: "dd.mm.yyyy" })(new Date()); const existingMetadata: LayoutMetadata = { id: existingId, name: "Existing Layout", group: "Group 1", screenshot: "screenshot", - user: "vuu user", + user: username, created: newDate, }; @@ -51,14 +61,14 @@ const metadataToAdd: LayoutMetadataDto = { name: "New Layout", group: "Group 1", screenshot: "screenshot", - user: "vuu user", + user: username, }; const metadataToUpdate: Omit = { name: "New Layout", group: "Group 1", screenshot: "screenshot", - user: "vuu user", + user: username, created: newDate, }; @@ -66,8 +76,8 @@ const layoutToAdd: LayoutJSON = { type: "t", }; -const metadataSaveLocation = "layouts/metadata"; -const layoutsSaveLocation = "layouts/layouts"; +const metadataSaveLocation = `layouts/metadata/${username}`; +const layoutsSaveLocation = `layouts/layouts/${username}`; afterEach(() => { localStorage.clear(); diff --git a/vuu-ui/packages/vuu-layout/test/layout-persistence/RemoteLayoutPersistenceManager.test.ts b/vuu-ui/packages/vuu-shell/test/layout-persistence/RemoteLayoutPersistenceManager.test.ts similarity index 93% rename from vuu-ui/packages/vuu-layout/test/layout-persistence/RemoteLayoutPersistenceManager.test.ts rename to vuu-ui/packages/vuu-shell/test/layout-persistence/RemoteLayoutPersistenceManager.test.ts index 213d1e6a9..68ab36fb6 100644 --- a/vuu-ui/packages/vuu-layout/test/layout-persistence/RemoteLayoutPersistenceManager.test.ts +++ b/vuu-ui/packages/vuu-shell/test/layout-persistence/RemoteLayoutPersistenceManager.test.ts @@ -2,24 +2,35 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { GetLayoutResponseDto, CreateLayoutResponseDto, - RemoteLayoutPersistenceManager, -} from "../../src/layout-persistence/RemoteLayoutPersistenceManager"; + RemotePersistenceManager, +} from "../../src/persistence-management/RemotePersistenceManager"; import { LayoutMetadata, LayoutMetadataDto } from "@finos/vuu-shell"; -import { LayoutJSON } from "../../src/layout-reducer"; +import { LayoutJSON } from "@finos/vuu-layout"; import { v4 as uuidv4 } from "uuid"; -import { expectPromiseRejectsWithError } from "./utils"; +import { expectPromiseRejectsWithError } from "@finos/vuu-utils/test/utils"; -const persistence = new RemoteLayoutPersistenceManager(); const mockFetch = vi.fn(); global.fetch = mockFetch; +const username = "vuu user"; + +vi.mock("@finos/vuu-shell", async () => { + return { + getAuthDetailsFromCookies: (): [string, string] => { + return [username, "token"]; + }, + }; +}); + +const persistence = new RemotePersistenceManager(); + const metadata: LayoutMetadata = { id: "0001", name: "layout 1", group: "group 1", screenshot: "screenshot", - user: "username", + user: username, created: "01.01.2000", }; @@ -27,7 +38,7 @@ const metadataToAdd: LayoutMetadataDto = { name: "layout 1", group: "group 1", screenshot: "screenshot", - user: "username", + user: username, }; const layout: LayoutJSON = { @@ -44,7 +55,7 @@ type FetchResponse = { statusText?: string; }; -describe("RemoteLayoutPersistenceManager", () => { +describe("RemotePersistenceManager", () => { beforeEach(() => { vi.clearAllMocks(); }); diff --git a/vuu-ui/packages/vuu-utils/test/screenshot-utils.test.ts b/vuu-ui/packages/vuu-shell/test/layout-persistence/screenshot-utils.test.ts similarity index 85% rename from vuu-ui/packages/vuu-utils/test/screenshot-utils.test.ts rename to vuu-ui/packages/vuu-shell/test/layout-persistence/screenshot-utils.test.ts index 9809fde58..465c62825 100644 --- a/vuu-ui/packages/vuu-utils/test/screenshot-utils.test.ts +++ b/vuu-ui/packages/vuu-shell/test/layout-persistence/screenshot-utils.test.ts @@ -1,38 +1,36 @@ -import { takeScreenshot } from "../src/screenshot-utils"; +import { takeScreenshot } from "../../src/layout-management/screenshot-utils"; import { describe, expect, it, vi } from "vitest"; +import { expectPromiseRejectsWithError } from "@finos/vuu-utils/test/utils"; +import htmlToImage from "html-to-image"; -/** - * The default environment in Vitest is a Node.js environment. If you are building a web application, you can use browser-like environment through either jsdom or happy-dom instead - * @vitest-environment happy-dom - */ +const node = document.createElement("div"); describe("takeScreenshot", () => { it("returns a string when toPng() promise is resolved", async () => { const placeholderImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAACWCAYAAADwkd5lAAAAAXNSR0IArs4c6QAADyRJREFUeF7tnLmLVE0Xh6tBxhmYwFlAnEwT/wEDcUk0MNdAwSUwUEQRBNFA3DEQFEFEFFwC9S9RQwWZRA3UZBRkFhBhXIL5qOt7+7vT0z11l6pbp6qehuZ1+tZy6jnn1q/Oud1vZ3p6eunPnz9qZGQkew8NDSleEIAABCAAgV4CWisWFxezt9aKzszMzNLk5KSan5/P3vo1Pj6evRETAggCEIBA2gS0aPTTh9nZ2X8CMjU11SX08+fPbuPR0dFMSMbGxlSn00mbIquHAAQgkAiBpaUltbCwkGmB1oQ8qdCakL++fv26UkDyi2UGSIQly4QABCCQBIEqCcSqAlKkNSiFocSVREyxSAhAIGICdff30gJSZFdFoSJmztIgAAEIBEvARoWploBQ4go2ZjAcAhBInIDNBKCRgFDiSjwSWT4EIBAEgbolKtPirAkIJS4Taq5DAAIQaI+AjRKVyVonAkKJy4Sd6xCAAATcELBZojJZ6FRAKHGZ8HMdAhCAQHMCrkpUJstaExBKXCZXcB0CEIBAeQJtlKhM1ngREEpcJrdwHQIQgEB/Am2WqEw+8CoglLhM7uE6BCAAAaV8lahM7MUICCUuk6u4DgEIpERAQonKxFukgFDiMrmN6xCAQKwEJJWoTIxFCwglLpP7uA4BCMRAQGqJysQ2GAGhxGVyJdchAIGQCIRQojLxDFJAKHGZ3Mp1CEBAKoGQSlQmhkELCCUuk3u5DgEISCAQaonKxC4aAaHEZXI11yEAgTYJxFCiMvGKUkAocZncznUIQMAVgZhKVCZGUQsIJS6T+7kOAQjYIBBricrEJhkBocRlCgWuQwACVQikUKIy8UhSQChxmcKC6xCAwCACKZWoTFGQtIBQ4jKFB9chAAFNINUSlcn7CEgfQpwwTGHDdQjET4ASldnHCMgqjAggcwDRAgKxEeAAWd6jCEhJVqSwJUHRDAIBEuD+ruc0BKQGN04oNaDRBQLCCFBhaO4QBKQBQwKwATy6QsATAQ6A9sAjIJZYkgJbAskwEHBAgPvTAVSlFALigCsnHAdQGRICFQlQIagIrEZzBKQGtLJdCOCypGgHAXsEOMDZY2kaCQExEbJ0nRTaEkiGgUAfAtxffsICAfHAnROSB+hMGR0BMnz/LkVAPPqAG8AjfKYOlgAHMDmuQ0CE+IIUXIgjMEMkAe4PkW7hW1gS3cIJS6JXsKltAmTobROvPh8ZSHVmrfXgBmoNNRMJIsABSpAzDKYgIIH4ihQ+EEdhZi0CxHctbN47ISDeXVDdAE5o1ZnRQx4BMmx5PqlqEQJSlZig9tyAgpyBKaUJcAAqjUp8QwREvIvKGUgJoBwnWvkhQHz64e56VgTENWEP43PC8wCdKVcQIEOOPygQkIh9zA0csXMFL40DjGDnWDYNAbEMVOpwlBCkeiYOu4ivOPxYdRUISFViEbTnhBiBEwUsgQxXgBM8m4CAeHaAz+nZAHzSD3duDiDh+s625QiIbaKBjkcJIlDHtWQ28dES6MCmQUACc1gb5nLCbIOy/DnIUOX7yLeFCIhvDwienw1EsHMcmsYBwiHcyIZGQCJzqKvlUMJwRVbGuPhXhh9CswIBCc1jAuzlhCrACRZMIMO0ADHxIRCQxAOgyfLZgJrQ89eXA4A/9rHNjIDE5lFP66EE4gl8yWnxT0lQNKtEAAGphIvGZQhwwi1DyX0bMkT3jFOfAQFJPQIcrp8NzCHcVYZGwP1wT3FWBCRFr3tYMyUUt9Dh65Yvo/cngIAQGa0T4IRsBzkZnh2OjFKfAAJSnx09GxJgA6wHEAGux41e9gkgIPaZMmINApRgVocGnxpBRRfnBBAQ54iZoCoBTtj/iJGhVY0c2rdNAAFpmzjzlSaQ6gaKgJYOERp6JoCAeHYA05cjEHsJJ/b1lfMyrUIjgICE5jHsVbGc0FPNsAjheAggIPH4MrmVhLoBxyKAyQUcC15BAAEhKKIgIL0EJN2+KIKARbROAAFpHTkTuiYg5YQfaobk2j+MHw8BBCQeX7KSHgK+NnApAkZAQMA1AQTENWHGF0HAdQnJ9fgiIGIEBHoIICCERHIEbGUIvjKc5BzGgsUSQEDEugbDXBOoKwC2BMj1+hgfAq4JICCuCTN+EARMJSjT9SAWiZEQsEwAAbEMlOHCJ5BnGHNzc2p4eDhb0O/fv9X4+Hj2Hh0dDX+RrAACFgggIBYgMkRcBIolqrVr12aL+/Xrl5qYmEBA4nI1q2lIAAFpCJDucRAwlahM1+OgwCogUI0AAlKNF60jIsBD9IicyVK8EEBAvGBnUp8EbH2Lqq4A+Vw7c0PAJoFv376pzszMzNLU1JTNcRkLAqIIuC5BuR5fFEyMgcB/BBAQQiFaAr4yBFsZTrSOYWHREKCEFY0rWUhOQMoG7kvAiAQItEWADKQt0szjlID0EpJ0+5w6h8GjJUAGEq1r419YqCd8KRlS/BHCCl0TIANxTZjxrROIZQMOVQCtO5QBgyVABhKs69IyPPYSUOzrSyta01ktApKOr4Nbaaon9FgyrOACDoMrE0BAKiOjg2sCbKD/CKcqoK7ji/HtEeAZiD2WjNSAACWc1eHBp0Fw0dUZAQTEGVoGNhHghG0i1P86GVo9bvSyT4ASln2mjGggwAZoJ0QQYDscGaU+AQSkPjt6ViBACaYCrBpN4VsDGl0aE0BAGiNkgEEEOCH7iQ0yPD/cU5yVZyApet3xmtnAHAMuOTwCXhIUzWoTIAOpjY6ORQKUUGTHA/6R7Z9QrUNAQvWcALs54QpwQg0TyBBrQKNLXwKUsAiMygTYgCojE9mBA4BItwRlFBlIUO7yZywlEH/s25gZ/7ZBOb45yEDi86m1FXFCtYYyqIHIMINyl1djyUC84pc5ORuITL+0bRUHiLaJhzcfAhKez5xYTAnDCdZoBiU+onGl1YUgIFZxhjUYJ8yw/CXFWjJUKZ7wbwfPQPz7oHUL2ABaRx7lhBxAonRrpUUhIJVwhduYEkS4vgvBcuIrBC/Zt5ESln2mYkbkhCjGFUkZQoabjrsRkAh9zQ0coVMDXBIHmACdVtFkBKQiMKnNKSFI9Qx2aQLEZ5xxwDOQgP3KCS9g5yVsOhlyPM4nAwnQl9yAAToNk1cQ4AAUflAgIIH4kBJAII7CzFoEiO9a2Lx3ooTl3QWDDeCEJtg5mOaMABm2M7TWByYDsY60+YDcQM0ZMkL4BDhAyfchGYgQH5HCC3EEZogkwP0h0i2KDMSjXzhheYTP1MESIEOX4zoExIMvuAE8QGfK6AhwAPPvUkpYLfmAFLwl0EyTJAHuLz9uR0AccueE5BAuQ0NgAAEy/PZCAwFxwJoAdgCVISFQkQAHuIrAajTnGUgNaP26kEJbAskwEHBAgPvTAVSlFBlIA66ccBrAoysEPBGgQmAPPBlIDZYEYA1odIGAMAIcAJs7hAykJENS4JKgaAaBAAlwf9dzGhnIKtw4odQLKnpBIGQCVBjKew8B6cOKACofQLSEQKwEOECaPUsJ6z9GpLDmYKEFBFIlwP7Q3/NJZyCcMFLdDlg3BOoToELxf3ZJZiAEQP2bh54QgMA/AhxAVTr/N15SUG57CEDAFYFU95eoS1icEFzdLowLAQgMIpBShSNKAUnJgdzGEICATAIpHGCjeQaSagop89bBKghAoEgg1v0paAFJQeG5DSEAgbgIxFQhCbKEFZMD4ro1WA0EIFCWQAwH4GAykFhTwLLBRjsIQCBeAqHub6IzkBgUOt6QZ2UQgIALAiFVWERmICEBdBFAjAkBCEAghAO0mAwk1BSOMIcABCDgmoDU/dGrgISgsK4Dg/EhAAEIVCEgqULjpYQlCUAVx9EWAhCAgG0C169fz4a8ePFid2j92aVLl7K/X716pbZv39699uLFC3Xo0KHs7wcPHqjdu3crvaeOj49n79HR0YEmLi4uqjNnzqjDhw93x8w/e/jwYbfftWvXuvZ8+PBB7d+/X717904dP35c3blzR42MjGRtW8tApKZgtoOB8SAAAQiUJfD69Wu1Y8cOVdyw9WdaQLRQvH//vvvviYkJpTfz06dPq7t372ZT5P/euHGjmp+fz976lYvJ0NBQ15SiUBRFaW5uTp06dUpduXJFbd68eZnpeZ+dO3eqvXv3ZuKj/33w4MGsndMMhBJV2TCiHQQgkBoBvTlfvnw5O9lrEckzkGJG0psxaFF5+fJlNwvQbTdt2tTd0DXDfhWe79+/qwMHDqitW7eqL1++ZHPlWY0WJS0e9+7dU1qkiq+iYGlx0eL27Nmz7vxOMhBKVKndCqwXAhCoSkCLgX59+vQp+6/e1Isnfn3K7/27t9yV/3327NksO9CvvMT0/Plz9fTpU3Xz5k2ls4x169apDRs2qGPHji0TkF5RKK6jmA1pcen921oGQomqavjQHgIQSJWA3tAvXLigbty4oe7fv79CQIrPKIpZRm/GoUVIC1Cv+GzZsqVb3tKZQ74/67bnzp1T58+fV3v27FG6xFV8pqIN0Z/rz3LBKGYcvdlKowyEElWq4c+6IQCBJgS0EOzatSsrI61WstJzlBUQ3bb4wFtnIPmzitxWLVy6lHXixIms9KUfuD958iR7dpJnLnq+mZmZ7O+3b98uK1lZERBKVE1Ch74QgEDKBPQm/PjxY3X16tXs20z9BCR/UF22hNX7Da5cAPJvSxUFRIuKbr9t2za1sLCQiUfxW1y6b/5wfnZ2dtlD/NolLEpUKYc8a4cABGwR6C0Z5ePmX5G9detW98F4v4foecmqNzvRf+sN/uTJk2r9+vXqyJEjfTOQXECKXw0u7u+fP39Wjx49ykprP378WPaAvdJDdEpUtkKGcSAAAQj0J9D7YLzO13j1cw5dnsrFYXJyctkzkH4ZiBaQfg/t9Vd6x8bGst+arFmzRt2+fTv7rcm+ffvKfY2XEhWhDgEIQKAdAk1+SJg/58jFQ4tCXs7SmY5+AJ4/ENerKYpMnoH0/pAwz4SGh4ezEtebN2+y34l8/PhRHT16NPu674ofEmrFMv0QpR2czAIBCEAAApIIDHqEoQWpMz09vfT3799MVbTqFH+92Ol0lC5lFV/6M/0qft7kMz3WoP5157Yx5qC5+629rJ1lx+wXPDmj3vlXa9s7X29bn2PWmdu09n5jrhbDpvEk3cTYAgEJBLSY6KxFv7VW/A8L/q17HrcSiwAAAABJRU5ErkJggg=="; - - // We need to mock the html-to-image package because the web API operations it relies on (e.g. canvas.toDataUrl) are not available in the test environment - const htmlToImage = await import("html-to-image"); htmlToImage.toPng = vi.fn().mockResolvedValue(placeholderImage); - const node = document.createElement("div"); - const screenshot = await takeScreenshot(node); expect(typeof screenshot).toEqual("string"); }); - it("returns undefined when toPng() promise is rejected", async () => { - // We need to mock the html-to-image package because the web API operations it relies on (e.g. canvas.toDataUrl) are not available in the test environment - const htmlToImage = await import("html-to-image"); + it("rejects with error message when toPng() promise is rejected", async () => { htmlToImage.toPng = vi.fn().mockRejectedValue({}); - const node = document.createElement("div"); - - const screenshot = await takeScreenshot(node); + expectPromiseRejectsWithError( + () => takeScreenshot(node), + "Error taking screenshot" + ); + }); - console.log(screenshot); + it("rejects with error message when toPng() resolves with falsey value", async () => { + htmlToImage.toPng = vi.fn().mockResolvedValue(undefined); - expect(screenshot).toBeUndefined(); + expectPromiseRejectsWithError( + () => takeScreenshot(node), + "No Screenshot available" + ); }); }); diff --git a/vuu-ui/packages/vuu-layout/test/layout-persistence/utils.ts b/vuu-ui/packages/vuu-shell/test/layout-persistence/utils.ts similarity index 100% rename from vuu-ui/packages/vuu-layout/test/layout-persistence/utils.ts rename to vuu-ui/packages/vuu-shell/test/layout-persistence/utils.ts diff --git a/vuu-ui/packages/vuu-table-extras/package.json b/vuu-ui/packages/vuu-table-extras/package.json index cb033461e..2e84f15f0 100644 --- a/vuu-ui/packages/vuu-table-extras/package.json +++ b/vuu-ui/packages/vuu-table-extras/package.json @@ -15,21 +15,20 @@ }, "dependencies": { "@finos/vuu-codemirror": "0.0.26", - "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-table-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-utils": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@lezer/lr": "1.3.4", - "@salt-ds/core": "1.8.0", - "@salt-ds/lab": "1.0.0-alpha.15" + "@salt-ds/core": "1.13.2" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" }, "type": "module" } diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.css b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.css deleted file mode 100644 index 64f0fff76..000000000 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.css +++ /dev/null @@ -1,103 +0,0 @@ -.vuuTable td:has(> .vuuBackgroundCell){ - padding: 0; - text-align: right; -} - -.vuuBackgroundCell { - color: var(--background-cell-color); - padding-right: var(--salt-size-unit); - position: relative; - z-index: -1; -} - -.vuuBackgroundCell-flasher { - background-color: var(--background-cell-background); - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - z-index: -1; -} - -.vuuBackgroundCell-flasher { - text-align: left; -} -.vuuBackgroundCell-flasher + .num { - padding-left: 8px; -} - -.right .vuuBackgroundCell-flasher { - text-align: right; -} -.right .vuuBackgroundCell-flasher + .num { - padding-right: 8px; -} - -.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-flasher { - background-color: transparent; -} - -.vuuBackgroundCell-backgroundOnly.up1, -.vuuBackgroundCell-backgroundArrow.up1 { - animation-duration: 30s; - animation-name: reactbgup1; -} - -.vuuBackgroundCell-backgroundOnly.up2, -.vuuBackgroundCell-backgroundArrow.up2 { - animation-duration: 30s; - animation-name: reactbgup2; -} - -.vuuBackgroundCell-backgroundOnly.down1, -.vuuBackgroundCell-backgroundArrow.down1 { - animation-duration: 30s; - animation-name: reactbgdown1; -} - -.vuuBackgroundCell-backgroundOnly.down2, -.vuuBackgroundCell-backgroundArrow.down2 { - animation-duration: 30s; - animation-name: reactbgdown2; -} - -.up1.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactarrowup1; -} - -.up2.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactarrowup2; -} - -.down1.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactarrowdown1; -} - -.down2.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactarrowdown2; -} - -.up1.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactbgarrowup1; -} - -.up2.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactbgarrowup2; -} - -.down1.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactbgarrowdown1; -} - -.down2.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-flasher { - animation-duration: 30s; - animation-name: reactbgarrowdown2; -} diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/index.ts b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/index.ts deleted file mode 100644 index ccb70a013..000000000 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./background-cell"; diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCell.css b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCell.css new file mode 100644 index 000000000..c24f5976b --- /dev/null +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCell.css @@ -0,0 +1,105 @@ + +.vuuBackgroundCell { + --background-animation-duration: 10s; + color: var(--vuuBackgroundCell-color, var(--vuu-color-gray-80)); + padding-right: var(--salt-size-unit); + position: relative; + z-index: -1; +} + +.vuuBackgroundCell-arrowBackground, +.vuuBackgroundCell-arrowOnly { + padding-left: 14px; +} + +.vuuBackgroundCell-arrow { + background-color: var(--background-cell-background); + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: -1; +} + +.vuuBackgroundCell-arrow { + text-align: left; +} +.vuuBackgroundCell-arrow + .num { + padding-left: 8px; +} + +.right .vuuBackgroundCell-arrow { + text-align: right; +} +.right .vuuBackgroundCell-arrow + .num { + padding-right: 8px; +} + +.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-arrow { + background-color: transparent; +} + +.vuuBackgroundCell-backgroundOnly.up1, +.vuuBackgroundCell-arrowBackground.up1 { + animation-duration: var(--background-animation-duration); + animation-name: vuubgup1; +} + +.vuuBackgroundCell-backgroundOnly.up2, +.vuuBackgroundCell-arrowBackground.up2 { + animation-duration: var(--background-animation-duration); + animation-name: vuubgup2; +} + +.vuuBackgroundCell-backgroundOnly.down1, +.vuuBackgroundCell-arrowBackground.down1 { + animation-duration: var(--background-animation-duration); + animation-name: vuubgdown1; +} + +.vuuBackgroundCell-backgroundOnly.down2, +.vuuBackgroundCell-arrowBackground.down2 { + animation-duration: var(--background-animation-duration); + animation-name: vuubgdown2; +} + +.up1.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuuarrowup1; +} + +.up2.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuuarrowup2; +} + +.down1.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuuarrowdown1; +} + +.down2.vuuBackgroundCell-arrowOnly > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuuarrowdown2; +} + +.up1.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuubgarrowup1; +} + +.up2.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuubgarrowup2; +} + +.down1.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuubgarrowdown1; +} + +.down2.vuuBackgroundCell-arrowBackground > .vuuBackgroundCell-arrow { + animation-duration: 30s; + animation-name: vuubgarrowdown2; +} diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCell.tsx similarity index 86% rename from vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.tsx rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCell.tsx index 0354e64e4..854e07fba 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCell.tsx @@ -1,3 +1,4 @@ +import { dataAndColumnUnchanged } from "@finos/vuu-table"; import { ColumnType, TableCellProps } from "@finos/vuu-table-types"; import { DOWN1, @@ -8,11 +9,12 @@ import { UP1, UP2, } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; +import { memo } from "react"; import { useDirection } from "./useDirection"; import "./BackgroundCell.css"; -import "./FlashingBackground.css"; +import "./BackgroundKeyframes.css"; const CHAR_ARROW_UP = String.fromCharCode(11014); const CHAR_ARROW_DOWN = String.fromCharCode(11015); @@ -37,8 +39,11 @@ const getFlashStyle = (colType?: ColumnType) => { return FlashStyle.BackgroundOnly; }; -// export to avoid tree shaking, component is not consumed directly -export const BackgroundCell = ({ column, columnMap, row }: TableCellProps) => { +export const BackgroundCell = memo(function BackgroundCell({ + column, + columnMap, + row, +}: TableCellProps) { //TODO what about click handling const { name, type, valueFormatter } = column; @@ -66,11 +71,12 @@ export const BackgroundCell = ({ column, columnMap, row }: TableCellProps) => { return (
-
{arrow}
+
{arrow}
{valueFormatter(row[dataIdx])}
); -}; +}, +dataAndColumnUnchanged); registerComponent( "vuu.price-move-background", diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.css b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCellConfigurationEditor.css similarity index 100% rename from vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.css rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCellConfigurationEditor.css diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCellConfigurationEditor.tsx similarity index 96% rename from vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.tsx rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCellConfigurationEditor.tsx index 611492243..35737802a 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundCellConfigurationEditor.tsx @@ -7,7 +7,7 @@ import { Dropdown, SingleSelectionHandler } from "@finos/vuu-ui-controls"; import "./BackgroundCellConfigurationEditor.css"; import { useCallback, useState } from "react"; -import { ColumnDescriptorCustomRenderer } from "packages/vuu-table-types"; +import type { ColumnDescriptorCustomRenderer } from "@finos/vuu-table-types"; const classBase = "vuuBackgroundCellConfiguration"; diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/FlashingBackground.css b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundKeyframes.css similarity index 74% rename from vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/FlashingBackground.css rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundKeyframes.css index 39d4277fc..b791e8260 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/FlashingBackground.css +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/BackgroundKeyframes.css @@ -1,61 +1,77 @@ -/* @property --background-cell-background { - syntax: ''; - initial-value: transparent; - inherits: false; -} */ -/* @property color { - syntax: ''; - initial-value: #15171B; - inherits: false; -} */ - -@keyframes reactbgup1 { - from { +@keyframes vuubgup1 { + 0% { background-color: var(--vuu-color-green-50); color: white; } - to { - background-color: transparent; + + 30% { + color: white; + } + 33% { color: var(--vuu-color-gray-80); + } + 100% { + background-color: transparent; + color: var(--vuu-color-gray-80); } } - @keyframes reactbgup2 { - from { + @keyframes vuubgup2 { + 0% { background-color: var(--vuu-color-green-50); - color: #ffffff; + color: white; } - to { + + 30% { + color: white; + } + 33% { + color: var(--vuu-color-gray-80); + } + + 100% { background-color: transparent; color: var(--vuu-color-gray-80); } } - @keyframes reactbgdown1 { - from { + @keyframes vuubgdown1 { + 0% { background-color: var(--vuu-color-red-50); color: white; } - to { + 30% { + color: white; + } + 33% { + color: var(--vuu-color-gray-80); + } + 100% { background-color: transparent; color: var(--vuu-color-gray-80); } } - @keyframes reactbgdown2 { - from { + @keyframes vuubgdown2 { + 0% { background-color: var(--vuu-color-red-50); color: white; } - to { + 30% { + color: white; + } + 33% { + color: var(--vuu-color-gray-80); + } + 100% { background-color: transparent; color: var(--vuu-color-gray-80); } } - @keyframes reactarrowup1 { + @keyframes vuuarrowup1 { from { color: var(--salt-differential-positive-foreground); } @@ -64,7 +80,7 @@ } } - @keyframes reactarrowup2 { + @keyframes vuuarrowup2 { from { color: var(--salt-differential-positive-foreground); } @@ -73,7 +89,7 @@ } } - @keyframes reactarrowdown1 { + @keyframes vuuarrowdown1 { from { color: var(--salt-differential-negative-foreground); } @@ -82,7 +98,7 @@ } } - @keyframes reactarrowdown2 { + @keyframes vuuarrowdown2 { from { color: var(--salt-differential-negative-foreground); } @@ -91,7 +107,7 @@ } } - @keyframes reactbgarrowup1 { + @keyframes vuubgarrowup1 { 0% { color: var(--salt-differential-positive-foreground); background-color: var(--vuu-color-green-50); @@ -106,7 +122,7 @@ } } - @keyframes reactbgarrowup2 { + @keyframes vuubgarrowup2 { 0% { color: var(--salt-differential-positive-foreground); background-color: var(--vuu-color-green-50); @@ -121,7 +137,7 @@ } } - @keyframes reactbgarrowdown1 { + @keyframes vuubgarrowdown1 { 0% { color: var(--salt-differential-negative-foreground); background-color: var(--vuu-color-red-50); @@ -136,7 +152,7 @@ } } - @keyframes reactbgarrowdown2 { + @keyframes vuubgarrowdown2 { 0% { color: var(--salt-differential-negative-foreground); background-color: var(--vuu-color-red-50); diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/index.ts b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/index.ts similarity index 100% rename from vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/index.ts rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/index.ts diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/useDirection.ts b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/useDirection.ts similarity index 100% rename from vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/useDirection.ts rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/background-cell/useDirection.ts diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/dropdown-cell/DropdownCell.css b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/dropdown-cell/DropdownCell.css similarity index 100% rename from vuu-ui/packages/vuu-table/src/cell-renderers/dropdown-cell/DropdownCell.css rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/dropdown-cell/DropdownCell.css diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/dropdown-cell/DropdownCell.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/dropdown-cell/DropdownCell.tsx similarity index 96% rename from vuu-ui/packages/vuu-table/src/cell-renderers/dropdown-cell/DropdownCell.tsx rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/dropdown-cell/DropdownCell.tsx index 03eac99d7..6b47a7964 100644 --- a/vuu-ui/packages/vuu-table/src/cell-renderers/dropdown-cell/DropdownCell.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/dropdown-cell/DropdownCell.tsx @@ -9,7 +9,7 @@ import { import { dispatchCustomEvent, registerComponent } from "@finos/vuu-utils"; import { VuuColumnDataType } from "@finos/vuu-protocol-types"; import { memo, useCallback, useState } from "react"; -import { dataAndColumnUnchanged } from "../cell-utils"; +import { dataAndColumnUnchanged } from "@finos/vuu-table"; import "./DropdownCell.css"; diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/dropdown-cell/index.ts b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/dropdown-cell/index.ts similarity index 100% rename from vuu-ui/packages/vuu-table/src/cell-renderers/dropdown-cell/index.ts rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/dropdown-cell/index.ts diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers/index.ts b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/index.ts index f3fd0c349..da98c68a5 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers/index.ts +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/index.ts @@ -1 +1,4 @@ +export * from "./background-cell"; +export * from "./dropdown-cell"; +export * from "./lookup-cell"; export * from "./progress-cell"; diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/lookup-cell/LookupCell.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/lookup-cell/LookupCell.tsx similarity index 87% rename from vuu-ui/packages/vuu-table/src/cell-renderers/lookup-cell/LookupCell.tsx rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/lookup-cell/LookupCell.tsx index 2b70be31d..254d2b4c9 100644 --- a/vuu-ui/packages/vuu-table/src/cell-renderers/lookup-cell/LookupCell.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/lookup-cell/LookupCell.tsx @@ -2,7 +2,7 @@ import { useLookupValues } from "@finos/vuu-data-react"; import { TableCellRendererProps } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-utils"; import { memo } from "react"; -import { dataAndColumnUnchanged } from "../cell-utils"; +import { dataAndColumnUnchanged } from "@finos/vuu-table/src/cell-renderers/cell-utils"; // const classBase = "vuuTableLookupCell"; diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/lookup-cell/index.ts b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/lookup-cell/index.ts similarity index 100% rename from vuu-ui/packages/vuu-table/src/cell-renderers/lookup-cell/index.ts rename to vuu-ui/packages/vuu-table-extras/src/cell-renderers/lookup-cell/index.ts diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx index 3667f80d7..ec2958b50 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx @@ -5,7 +5,7 @@ import { isValidNumber, registerComponent, } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import { CSSProperties } from "react"; import "./ProgressCell.css"; diff --git a/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts b/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts index 051da9733..9a7bd6ea0 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts +++ b/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts @@ -13,11 +13,6 @@ import { } from "@finos/vuu-data-react"; import { ColumnDescriptor } from "@finos/vuu-table-types"; import { VuuTable } from "@finos/vuu-protocol-types"; -import { - ColumnExpressionOperator, - ColumnExpressionSuggestionType, - IExpressionSuggestionProvider, -} from "@finos/vuu-table-extras"; import { isNumericColumn, isTextColumn } from "@finos/vuu-utils"; import { useCallback, useRef } from "react"; import { @@ -25,6 +20,11 @@ import { columnFunctionDescriptors, } from "./column-function-descriptors"; import { functionDocInfo } from "./functionDocInfo"; +import { + ColumnExpressionOperator, + ColumnExpressionSuggestionType, + IExpressionSuggestionProvider, +} from "./useColumnExpressionEditor"; const NO_OPERATORS = [] as Completion[]; diff --git a/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx index 4cb2ec51f..d0be5e453 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-table-types"; +import { ColumnDescriptor, ColumnSettingsProps } from "@finos/vuu-table-types"; import { Dropdown } from "@finos/vuu-ui-controls"; import { getCalculatedColumnExpression, @@ -12,7 +12,6 @@ import { ColumnExpressionSubmitHandler, useColumnExpressionSuggestionProvider, } from "../column-expression-input"; -import { ColumnSettingsProps } from "../column-settings"; import { useColumnExpression } from "./useColumnExpression"; const classBase = "vuuColumnExpressionPanel"; diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/NumericFormattingSettings.tsx b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/BaseNumericFormattingSettings.tsx similarity index 87% rename from vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/NumericFormattingSettings.tsx rename to vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/BaseNumericFormattingSettings.tsx index 83ba314e6..a8a7d87b2 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/NumericFormattingSettings.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/BaseNumericFormattingSettings.tsx @@ -1,6 +1,5 @@ -import { FormField, FormFieldLabel, Input } from "@salt-ds/core"; -import { Switch } from "@salt-ds/lab"; -import { ColumnDescriptor, ColumnTypeFormatting } from "@finos/vuu-table-types"; +import { FormField, FormFieldLabel, Input, Switch } from "@salt-ds/core"; +import { ColumnTypeFormatting } from "@finos/vuu-table-types"; import { getTypeFormattingFromColumn } from "@finos/vuu-utils"; import { ChangeEvent, @@ -9,18 +8,14 @@ import { useCallback, useState, } from "react"; +import { FormattingSettingsProps } from "./types"; const classBase = "vuuFormattingSettings"; -export interface NumericFormattingSettingsProps { - column: ColumnDescriptor; - onChange: (formatting: ColumnTypeFormatting) => void; -} - -export const NumericFormattingSettings = ({ +export const BaseNumericFormattingSettings = ({ column, - onChange, -}: NumericFormattingSettingsProps) => { + onChangeFormatting: onChange, +}: FormattingSettingsProps) => { const [formattingSettings, setFormattingSettings] = useState(getTypeFormattingFromColumn(column)); diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx index 66487bb75..a44580337 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx @@ -1,7 +1,6 @@ import { ColumnDescriptor, ColumnDescriptorCustomRenderer, - ColumnTypeFormatting, ColumnTypeRendering, } from "@finos/vuu-table-types"; import { Dropdown, SingleSelectionHandler } from "@finos/vuu-ui-controls"; @@ -14,17 +13,19 @@ import { isTypeDescriptor, } from "@finos/vuu-utils"; import { FormField, FormFieldLabel } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, useCallback, useMemo } from "react"; -import { NumericFormattingSettings } from "./NumericFormattingSettings"; +import { BaseNumericFormattingSettings } from "./BaseNumericFormattingSettings"; +import { LongTypeFormattingSettings } from "./LongTypeFormattingSettings"; +import { FormattingSettingsProps } from "./types"; const classBase = "vuuColumnFormattingPanel"; export interface ColumnFormattingPanelProps - extends HTMLAttributes { + extends HTMLAttributes, + FormattingSettingsProps { availableRenderers: CellRendererDescriptor[]; column: ColumnDescriptor; - onChangeFormatting: (formatting: ColumnTypeFormatting) => void; onChangeRendering: (renderProps: ColumnTypeRendering) => void; } @@ -35,24 +36,15 @@ export const ColumnFormattingPanel = ({ className, column, onChangeFormatting, + onChangeType, onChangeRendering, ...htmlAttributes }: ColumnFormattingPanelProps) => { - const contentForType = useMemo(() => { - switch (column.serverDataType) { - case "double": - case "int": - case "long": - return ( - - ); - default: - return null; - } - }, [column, onChangeFormatting]); + const formattingSettingsForType = useMemo( + () => + formattingSettingsByColType({ column, onChangeFormatting, onChangeType }), + [column, onChangeFormatting, onChangeType] + ); const ConfigEditor = useMemo< React.FC | undefined @@ -81,7 +73,7 @@ export const ColumnFormattingPanel = ({ const handleChangeRenderer = useCallback< SingleSelectionHandler >( - (evt, cellRendererDescriptor) => { + (_, cellRendererDescriptor) => { const renderProps: ColumnTypeRendering = { name: cellRendererDescriptor.name, }; @@ -112,7 +104,7 @@ export const ColumnFormattingPanel = ({
- {contentForType} + {formattingSettingsForType} {ConfigEditor ? ( ); }; + +function formattingSettingsByColType(props: FormattingSettingsProps) { + const { column } = props; + + switch (column.serverDataType) { + case "double": + case "int": + return ; + case "long": + return ; + default: + return null; + } +} diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/DateTimeFormattingSettings.tsx b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/DateTimeFormattingSettings.tsx new file mode 100644 index 000000000..7faeff7d9 --- /dev/null +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/DateTimeFormattingSettings.tsx @@ -0,0 +1,118 @@ +import React, { SyntheticEvent, useCallback, useMemo, useState } from "react"; +import { Dropdown, SingleSelectionHandler } from "@finos/vuu-ui-controls"; +import { + DateTimePattern, + defaultPatternsByType, + fallbackDateTimePattern, + getTypeFormattingFromColumn, + supportedDateTimePatterns, +} from "@finos/vuu-utils"; +import { + FormField, + FormFieldLabel, + ToggleButton, + ToggleButtonGroup, +} from "@salt-ds/core"; +import { DateTimeColumnDescriptor } from "@finos/vuu-table-types"; +import { FormattingSettingsProps } from "./types"; + +export const DateTimeFormattingSettings: React.FC< + FormattingSettingsProps +> = ({ column, onChangeFormatting: onChange }) => { + const formatting = getTypeFormattingFromColumn(column); + const { pattern = fallbackDateTimePattern } = formatting; + const toggleValue = useMemo(() => getToggleValue(pattern), [pattern]); + + const [fallbackState, setFallbackState] = useState>( + { + time: pattern.time ?? defaultPatternsByType.time, + date: pattern.date ?? defaultPatternsByType.date, + } + ); + + const onPatternChange = useCallback( + (pattern: DateTimePattern) => onChange({ ...formatting, pattern }), + [onChange, formatting] + ); + + const onDropdownChange = useCallback< + ( + key: T + ) => SingleSelectionHandler[T]> + >( + (key) => (_, p) => { + const updatedPattern = { ...(pattern ?? {}), [key]: p }; + setFallbackState((s) => ({ + time: updatedPattern.time ?? s.time, + date: updatedPattern.date ?? s.date, + })); + onPatternChange(updatedPattern); + }, + [onPatternChange, pattern] + ); + + const onToggleChange = useCallback( + (evnt: SyntheticEvent) => { + const value = evnt.currentTarget.value as ToggleValue; + switch (value) { + case "time": + return onPatternChange({ + [value]: pattern[value] ?? fallbackState[value], + }); + case "date": + return onPatternChange({ + [value]: pattern[value] ?? fallbackState[value], + }); + case "both": + return onPatternChange({ + time: pattern.time ?? fallbackState.time, + date: pattern.date ?? fallbackState.date, + }); + } + }, + [onPatternChange, pattern, fallbackState] + ); + + return ( + <> + + {"Display"} + + {toggleValues.map((v) => ( + + {v.toUpperCase()} + + ))} + + + + {(["date", "time"] as const) + .filter((v) => !!pattern[v]) + .map((v) => ( + + {`${labelByType[v]} pattern`} + [typeof v]> + onSelectionChange={onDropdownChange(v)} + selected={pattern[v]} + source={supportedDateTimePatterns[v]} + width="100%" + /> + + ))} + + ); +}; + +const labelByType = { date: "Date", time: "Time" } as const; + +const toggleValues = ["date", "time", "both"] as const; + +type ToggleValue = (typeof toggleValues)[number]; + +function getToggleValue(pattern: DateTimePattern): ToggleValue { + return !pattern.time ? "date" : !pattern.date ? "time" : "both"; +} diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/LongTypeFormattingSettings.css b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/LongTypeFormattingSettings.css new file mode 100644 index 000000000..3fda3137e --- /dev/null +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/LongTypeFormattingSettings.css @@ -0,0 +1,6 @@ +.vuuLongColumnFormattingSettings { + display: flex; + flex-direction: column; + gap: 4px; + padding-top: 6px; +} diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/LongTypeFormattingSettings.tsx b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/LongTypeFormattingSettings.tsx new file mode 100644 index 000000000..410138d47 --- /dev/null +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/LongTypeFormattingSettings.tsx @@ -0,0 +1,58 @@ +import React, { useCallback } from "react"; +import { + FormField, + FormFieldLabel, + ToggleButton, + ToggleButtonGroup, +} from "@salt-ds/core"; +import { isDateTimeColumn, isTypeDescriptor } from "@finos/vuu-utils"; +import { DateTimeFormattingSettings } from "./DateTimeFormattingSettings"; +import { BaseNumericFormattingSettings } from "./BaseNumericFormattingSettings"; +import { FormattingSettingsProps } from "./types"; + +import "./LongTypeFormattingSettings.css"; + +const classBase = "vuuLongColumnFormattingSettings"; + +export const LongTypeFormattingSettings: React.FC = ( + props +) => { + const { column, onChangeType } = props; + const type = isTypeDescriptor(column.type) ? column.type.name : column.type; + + const handleToggleChange = useCallback( + (event: React.SyntheticEvent) => { + const value = event.currentTarget.value as ToggleValue; + onChangeType(value); + }, + [onChangeType] + ); + + return ( +
+ + {"Type inferred as"} + + {toggleValues.map((v) => ( + + {v.toUpperCase()} + + ))} + + + + {isDateTimeColumn(column) ? ( + + ) : ( + + )} +
+ ); +}; + +const toggleValues = ["number", "date/time"] as const; +type ToggleValue = (typeof toggleValues)[number]; diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/index.ts b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/index.ts index 5fb5a4db1..ed9c25e9b 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/index.ts +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/index.ts @@ -1,2 +1,3 @@ export * from "./ColumnFormattingPanel"; -export * from "./NumericFormattingSettings"; +export * from "./BaseNumericFormattingSettings"; +export * from "./DateTimeFormattingSettings"; diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/types.ts b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/types.ts new file mode 100644 index 000000000..981194aa5 --- /dev/null +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/types.ts @@ -0,0 +1,13 @@ +import { + ColumnDescriptor, + ColumnTypeFormatting, + ColumnTypeSimple, +} from "@finos/vuu-table-types"; + +export interface FormattingSettingsProps< + T extends ColumnDescriptor = ColumnDescriptor +> { + column: T; + onChangeFormatting: (formatting: ColumnTypeFormatting) => void; + onChangeType: (type: ColumnTypeSimple) => void; +} diff --git a/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx b/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx index 572ef49ff..93f7be278 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx @@ -1,13 +1,12 @@ +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { List, ListItem, ListItemProps, ListProps, } from "@finos/vuu-ui-controls"; -import { Checkbox } from "@salt-ds/core"; -import { Switch } from "@salt-ds/lab"; -import cx from "classnames"; -import { ColumnDescriptor } from "@finos/vuu-table-types"; +import { Checkbox, Switch } from "@salt-ds/core"; +import cx from "clsx"; import { HTMLAttributes, MouseEventHandler, @@ -15,9 +14,9 @@ import { useCallback, } from "react"; import { ColumnItem } from "../table-settings"; +import { getColumnLabel } from "@finos/vuu-utils"; import "./ColumnList.css"; -import { getColumnLabel } from "@finos/vuu-utils"; const classBase = "vuuColumnList"; const classBaseListItem = "vuuColumnListItem"; diff --git a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx index 088eab448..d37f9cee7 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx @@ -1,5 +1,5 @@ import { ColumnDescriptor } from "@finos/vuu-table-types"; -import cx from "classnames"; +import cx from "clsx"; import { getCalculatedColumnDetails, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx index c0cb8e6f3..990cb857d 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx @@ -1,5 +1,4 @@ -import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types"; -import { VuuTable } from "@finos/vuu-protocol-types"; +import { ColumnDescriptor, ColumnSettingsProps } from "@finos/vuu-table-types"; import { VuuInput } from "@finos/vuu-ui-controls"; import { getCalculatedColumnName, @@ -13,8 +12,7 @@ import { ToggleButton, ToggleButtonGroup, } from "@salt-ds/core"; -import cx from "classnames"; -import { HTMLAttributes } from "react"; +import cx from "clsx"; import { ColumnExpressionPanel } from "../column-expression-panel"; import { ColumnFormattingPanel } from "../column-formatting-settings"; import { ColumnNameLabel } from "./ColumnNameLabel"; @@ -33,15 +31,6 @@ const getColumnLabel = (column: ColumnDescriptor) => { } }; -export interface ColumnSettingsProps extends HTMLAttributes { - column: ColumnDescriptor; - onConfigChange: (config: TableConfig) => void; - onCancelCreateColumn: () => void; - onCreateCalculatedColumn: (column: ColumnDescriptor) => void; - tableConfig: TableConfig; - vuuTable: VuuTable; -} - export const ColumnSettingsPanel = ({ column: columnProp, onCancelCreateColumn, @@ -62,6 +51,7 @@ export const ColumnSettingsPanel = ({ onChangeCalculatedColumnName, onChangeFormatting, onChangeRendering, + onChangeType, onEditCalculatedColumn, onInputCommit, onSave, @@ -76,7 +66,6 @@ export const ColumnSettingsPanel = ({ const { serverDataType, align = getDefaultAlignment(serverDataType), - name, pin, width, } = column; @@ -172,6 +161,7 @@ export const ColumnSettingsPanel = ({ column={column} onChangeFormatting={onChangeFormatting} onChangeRendering={onChangeRendering} + onChangeType={onChangeType} /> {editCalculatedColumn ? ( diff --git a/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts b/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts index 0ac991b6c..c8ae62036 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts +++ b/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts @@ -2,6 +2,8 @@ import { ColumnDescriptor, TableConfig, ColumnTypeFormatting, + ColumnSettingsProps, + ColumnTypeSimple, } from "@finos/vuu-table-types"; import { @@ -12,6 +14,7 @@ import { isValidPinLocation, setCalculatedColumnName, updateColumnRenderProps, + updateColumnFormatting, updateColumnType, } from "@finos/vuu-utils"; import { @@ -22,7 +25,6 @@ import { useRef, useState, } from "react"; -import { ColumnSettingsProps } from "./ColumnSettingsPanel"; const integerCellRenderers: CellRendererDescriptor[] = [ { @@ -50,6 +52,10 @@ const stringCellRenderers: CellRendererDescriptor[] = [ ...getRegisteredCellRenderers("string"), ]; +const booleanCellRenderers: CellRendererDescriptor[] = [ + ...getRegisteredCellRenderers("boolean"), +]; + const getAvailableCellRenderers = ( column: ColumnDescriptor ): CellRendererDescriptor[] => { @@ -62,6 +68,8 @@ const getAvailableCellRenderers = ( return integerCellRenderers; case "double": return doubleCellRenderers; + case "boolean": + return booleanCellRenderers; default: return stringCellRenderers; } @@ -180,13 +188,22 @@ export const useColumnSettings = ({ const handleChangeFormatting = useCallback( (formatting: ColumnTypeFormatting) => { - const newColumn: ColumnDescriptor = updateColumnType(column, formatting); + const newColumn = updateColumnFormatting(column, formatting); setColumn(newColumn); onConfigChange(replaceColumn(tableConfig, newColumn)); }, [column, onConfigChange, tableConfig] ); + const handleChangeType = useCallback( + (type: ColumnTypeSimple) => { + const updatedColumn = updateColumnType(column, type); + setColumn(updatedColumn); + onConfigChange(replaceColumn(tableConfig, updatedColumn)); + }, + [column, onConfigChange, tableConfig] + ); + const handleChangeRendering = useCallback( (renderProps) => { if (renderProps) { @@ -247,6 +264,7 @@ export const useColumnSettings = ({ onChangeCalculatedColumnName: handleChangeCalculatedColumnName, onChangeFormatting: handleChangeFormatting, onChangeRendering: handleChangeRendering, + onChangeType: handleChangeType, onEditCalculatedColumn: handleEditCalculatedcolumn, onInputCommit: handleInputCommit, onSave: handleSaveCalculatedColumn, diff --git a/vuu-ui/packages/vuu-table-extras/src/datasource-stats/DatasourceStats.tsx b/vuu-ui/packages/vuu-table-extras/src/datasource-stats/DatasourceStats.tsx index 655db1446..8580ba340 100644 --- a/vuu-ui/packages/vuu-table-extras/src/datasource-stats/DatasourceStats.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/datasource-stats/DatasourceStats.tsx @@ -1,9 +1,9 @@ -import { DataSource } from "@finos/vuu-data"; +import { DataSource } from "@finos/vuu-data-types"; +import { VuuRange } from "@finos/vuu-protocol-types"; +import cx from "clsx"; import { HTMLAttributes, useEffect, useState } from "react"; -import cx from "classnames"; import "./DatasourceStats.css"; -import { VuuRange } from "@finos/vuu-protocol-types"; interface DataSourceStatsProps extends HTMLAttributes { dataSource: DataSource; diff --git a/vuu-ui/packages/vuu-table-extras/src/index.ts b/vuu-ui/packages/vuu-table-extras/src/index.ts index a1fcb8c9f..8833d7355 100644 --- a/vuu-ui/packages/vuu-table-extras/src/index.ts +++ b/vuu-ui/packages/vuu-table-extras/src/index.ts @@ -1,6 +1,5 @@ export * from "./cell-edit-validators"; export * from "./cell-renderers"; -export * from "./cell-renderers-next"; export * from "./column-list"; export * from "./column-settings"; export * from "./column-expression-input"; @@ -8,4 +7,3 @@ export * from "./column-expression-panel"; export * from "./column-formatting-settings"; export * from "./datasource-stats"; export * from "./table-settings"; -export * from "./useTableAndColumnSettings"; diff --git a/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx index 2662cf925..7da4e5782 100644 --- a/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx @@ -6,9 +6,7 @@ import { ToggleButton, ToggleButtonGroup, } from "@salt-ds/core"; -import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-table-types"; -import { HTMLAttributes } from "react"; +import { TableSettingsProps } from "@finos/vuu-table-types"; import { ColumnList } from "../column-list"; import { useTableSettings } from "./useTableSettings"; @@ -16,15 +14,6 @@ import "./TableSettingsPanel.css"; const classBase = "vuuTableSettingsPanel"; -export interface TableSettingsProps extends HTMLAttributes { - availableColumns: SchemaColumn[]; - onAddCalculatedColumn: () => void; - onConfigChange: (config: TableConfig) => void; - onDataSourceConfigChange: (dataSOurceConfig: DataSourceConfig) => void; - onNavigateToColumn?: (columnName: string) => void; - tableConfig: TableConfig; -} - /** The TableSettingsPanel assumes 'ownership' of the tableSettings. It updates the settings in state locally and notifies caller of @@ -37,7 +26,6 @@ export const TableSettingsPanel = ({ onDataSourceConfigChange, onNavigateToColumn, tableConfig: tableConfigProp, - ...htmlAttributes }: TableSettingsProps) => { const { columnItems, @@ -55,7 +43,7 @@ export const TableSettingsPanel = ({ }); return ( -
+
Column Labels void; - export type TableHeading = { label: string; width: number }; export type TableHeadings = TableHeading[][]; @@ -81,7 +78,7 @@ export interface GridConfig extends TableConfig { export declare type ColumnTypeFormatting = { alignOnDecimals?: boolean; decimals?: number; - pattern?: string; + pattern?: DateTimePattern; zeroPad?: boolean; }; @@ -132,7 +129,19 @@ export interface ValueListRenderer { values: string[]; } -export declare type DateTimeColumnTypeSimple = "date" | "time"; +export declare type DateTimeColumnTypeSimple = "date/time"; + +type DateTimeColumnType = + | DateTimeColumnTypeSimple + | (Omit & { name: DateTimeColumnTypeSimple }); + +export declare type DateTimeColumnDescriptor = Omit< + ColumnDescriptor, + "type" +> & { + type: DateTimeColumnType; +}; + export declare type ColumnTypeSimple = | "string" | "number" @@ -184,9 +193,9 @@ export interface ColumnDescriptor { colHeaderLabelRenderer?: string; editable?: boolean; flex?: number; - /** + /** Optional additional level(s) of heading to display above label. - May span multiple columns, if multiple adjacent columns declare + May span multiple columns, if multiple adjacent columns declare same heading at same level. */ heading?: string[]; @@ -275,3 +284,50 @@ export type GridAction = | ScrollAction | GridActionResizeCol | GridActionSelection; + +/** + * Describes the props for a Column Configuration Editor, for which + * an implementation is provided in vuu-table-extras + */ +export interface ColumnSettingsProps { + column: ColumnDescriptor; + onConfigChange: (config: TableConfig) => void; + onCancelCreateColumn: () => void; + onCreateCalculatedColumn: (column: ColumnDescriptor) => void; + tableConfig: TableConfig; + vuuTable: VuuTable; +} + +/** + * Describes the props for a Table Configuration Editor, for which + * an implementation is provided in vuu-table-extras + */ +export interface TableSettingsProps { + availableColumns: SchemaColumn[]; + onAddCalculatedColumn: () => void; + onConfigChange: (config: TableConfig) => void; + onDataSourceConfigChange: (dataSOurceConfig: DataSourceConfig) => void; + onNavigateToColumn?: (columnName: string) => void; + tableConfig: TableConfig; +} + +export type DefaultColumnConfiguration = ( + tableName: T, + columnName: string +) => Partial | undefined; + +export type ResizePhase = "begin" | "resize" | "end"; + +export type TableColumnResizeHandler = ( + phase: ResizePhase, + columnName: string, + width?: number +) => void; + +export interface HeaderCellProps extends HTMLAttributes { + classBase?: string; + column: RuntimeColumnDescriptor; + onResize?: TableColumnResizeHandler; +} + +export type TableConfigChangeHandler = (config: TableConfig) => void; diff --git a/vuu-ui/packages/vuu-table/package.json b/vuu-ui/packages/vuu-table/package.json index b852b632c..f46fa8447 100644 --- a/vuu-ui/packages/vuu-table/package.json +++ b/vuu-ui/packages/vuu-table/package.json @@ -8,22 +8,21 @@ "build": "node ../../scripts/run-build.mjs", "type-defs": "node ../../scripts/build-type-defs.mjs" }, - "dependencies": { - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15", - "@finos/vuu-data": "0.0.26", - "@finos/vuu-data-react": "0.0.26", + "devDependencies": { "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26" + }, + "dependencies": { + "@salt-ds/core": "1.13.2", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", - "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" } } diff --git a/vuu-ui/packages/vuu-table/src/Row.tsx b/vuu-ui/packages/vuu-table/src/Row.tsx index 29a4f45ec..1309e484d 100644 --- a/vuu-ui/packages/vuu-table/src/Row.tsx +++ b/vuu-ui/packages/vuu-table/src/Row.tsx @@ -13,7 +13,7 @@ import { isNotHidden, RowSelected, } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import { CSSProperties, memo, MouseEvent, useCallback } from "react"; import { TableCell, TableGroupCell } from "./table-cell"; @@ -92,7 +92,7 @@ export const Row = memo( return (
void; - export type TableNavigationStyle = "none" | "cell" | "row"; export interface TableProps @@ -55,6 +54,10 @@ export interface TableProps * required if a fully featured column picker is to be available */ availableColumns?: SchemaColumn[]; + /** + * Provide configuration settings for Table. At minimun, column + * descriptors must be provided. + */ config: TableConfig; dataSource: DataSource; disableFocus?: boolean; @@ -76,7 +79,7 @@ export interface TableProps * is changed. By persisting this value and providing it to the Table as a * prop, table state can be persisted across sessions. */ - onConfigChange?: (config: TableConfig) => void; + onConfigChange?: TableConfigChangeHandler; onDragStart?: DragStartHandler; onDrop?: (dragDropState: DragDropState) => void; /** @@ -229,6 +232,7 @@ const TableCore = ({
{showColumnHeaders ? ( @@ -304,6 +308,15 @@ export const Table = forwardRef(function TableNext( const [size, setSize] = useState(); + if (config === undefined) { + throw Error( + "vuu Table requires config prop. Minimum config is list of Column Descriptors" + ); + } + if (dataSource === undefined) { + throw Error("vuu Table requires dataSource prop"); + } + return ( p.column === p1.column && - p.row[p.columnMap[p.column.name]] === p1.row[p1.columnMap[p1.column.name]]; + p.column.valueFormatter(p.row[p.columnMap[p.column.name]]) === + p1.column.valueFormatter(p1.row[p1.columnMap[p1.column.name]]); diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx b/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx index a5a6f9c5d..ad09492df 100644 --- a/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx +++ b/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx @@ -21,7 +21,7 @@ export const CheckboxCell: React.FC = memo( [onCommit] ); - return !!column.editable ? ( + return column.editable ? ( ) : ( diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts b/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts index dfa5e7706..5c65fcf6a 100644 --- a/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts +++ b/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts @@ -1,5 +1,4 @@ export * from "./checkbox-cell"; -export * from "./dropdown-cell"; export * from "./input-cell"; -export * from "./lookup-cell"; export * from "./toggle-cell"; +export * from "./cell-utils"; diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx b/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx index 97e69e160..54c716f84 100644 --- a/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx +++ b/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx @@ -2,10 +2,7 @@ import { TableCellRendererProps } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-utils"; import { Input } from "@salt-ds/core"; import { useEditableText } from "@finos/vuu-ui-controls"; -import cx from "classnames"; -// make sure all validators are loaded - how do we manage this ? -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import { CaseValidator, PatternValidator } from "@finos/vuu-table-extras"; +import cx from "clsx"; import "./InputCell.css"; @@ -24,14 +21,10 @@ export const InputCell = ({ row, }: TableCellRendererProps) => { const dataIdx = columnMap[column.name]; - const { - align = "left", - clientSideEditValidationCheck, - valueFormatter, - } = column; + const { align = "left", clientSideEditValidationCheck } = column; const { warningMessage, ...editProps } = useEditableText({ - initialValue: valueFormatter(row[dataIdx]), + initialValue: row[dataIdx], onCommit, clientSideEditValidationCheck, }); diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx b/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx index ad3d8006a..a7e76742e 100644 --- a/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx +++ b/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx @@ -9,7 +9,7 @@ import { isValueListRenderer, registerComponent, } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import { memo, useCallback } from "react"; import { dataAndColumnUnchanged } from "../cell-utils"; diff --git a/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx b/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx index 7fc41e808..37d7660ea 100644 --- a/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx +++ b/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { HTMLAttributes, MouseEvent, useCallback } from "react"; diff --git a/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx b/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx index a000fd237..7bc1204ab 100644 --- a/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx +++ b/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx @@ -1,6 +1,6 @@ import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { useContextMenu } from "@finos/vuu-popups"; -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, MouseEvent, diff --git a/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx b/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx index ac8f16928..cac7f5f3c 100644 --- a/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx +++ b/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx @@ -1,12 +1,9 @@ -import { Heading, RuntimeColumnDescriptor } from "@finos/vuu-table-types"; +import { + Heading, + ResizePhase, + RuntimeColumnDescriptor, +} from "@finos/vuu-table-types"; import { RefObject, useCallback, useRef, useState } from "react"; -import { ResizePhase } from "../useTableModel"; - -export type TableColumnResizeHandler = ( - phase: ResizePhase, - columnName: string, - width?: number -) => void; export type ResizeHandler = (evt: MouseEvent, moveBy: number) => void; export interface CellResizeHookProps { diff --git a/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts b/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts index 72ffffcdf..38d9744dd 100644 --- a/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts +++ b/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts @@ -1,5 +1,8 @@ -import { DataSource } from "@finos/vuu-data"; -import { ContextMenuItemDescriptor, MenuBuilder } from "@finos/vuu-data-types"; +import { + ContextMenuItemDescriptor, + DataSource, + MenuBuilder, +} from "@finos/vuu-data-types"; import { RuntimeColumnDescriptor, PinLocation } from "@finos/vuu-table-types"; import { isNumericColumn } from "@finos/vuu-utils"; diff --git a/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts b/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts index 4f7ee9364..a250b68cc 100644 --- a/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts +++ b/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts @@ -1,10 +1,13 @@ /* eslint-disable no-sequences */ -import { DataSource } from "@finos/vuu-data"; import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { Filter } from "@finos/vuu-filter-types"; import { removeColumnFromFilter } from "@finos/vuu-utils"; import { VuuFilter } from "@finos/vuu-protocol-types"; -import { DataSourceFilter, MenuActionHandler } from "@finos/vuu-data-types"; +import { + DataSource, + DataSourceFilter, + MenuActionHandler, +} from "@finos/vuu-data-types"; import { PersistentColumnAction } from "../useTableModel"; import { addGroupColumn, diff --git a/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx b/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx index 333bbaaf0..b28b4e1de 100644 --- a/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx +++ b/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx @@ -1,15 +1,16 @@ +import { OverflowContainer } from "@finos/vuu-layout"; import { ColumnDescriptor, GroupColumnDescriptor, + HeaderCellProps, RuntimeColumnDescriptor, } from "@finos/vuu-table-types"; -import cx from "classnames"; +import { useLayoutEffectSkipFirst } from "@finos/vuu-utils"; +import cx from "clsx"; import { useCallback, useRef, useState } from "react"; +import { ColumnHeaderPill, GroupColumnPill } from "../column-header-pill"; import { ColumnResizer, useTableColumnResize } from "../column-resizing"; -import { HeaderCellProps } from "./HeaderCell"; import { useCell } from "../useCell"; -import { ColumnHeaderPill, GroupColumnPill } from "../column-header-pill"; -import { OverflowContainer, useLayoutEffectSkipFirst } from "@finos/vuu-layout"; import "./GroupHeaderCell.css"; diff --git a/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx b/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx index 828e439cd..45a570acf 100644 --- a/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx +++ b/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx @@ -1,25 +1,15 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; -import { HTMLAttributes, MouseEventHandler, useCallback, useRef } from "react"; -import { useCell } from "../useCell"; -import { ColumnMenu } from "../column-menu"; +import { HeaderCellProps } from "@finos/vuu-table-types"; +import cx from "clsx"; +import { MouseEventHandler, useCallback, useRef } from "react"; import { SortIndicator } from "../column-header-pill"; -import cx from "classnames"; -import { - ColumnResizer, - TableColumnResizeHandler, - useTableColumnResize, -} from "../column-resizing"; +import { ColumnMenu } from "../column-menu"; +import { ColumnResizer, useTableColumnResize } from "../column-resizing"; +import { useCell } from "../useCell"; import "./HeaderCell.css"; const classBase = "vuuTableHeaderCell"; -export interface HeaderCellProps extends HTMLAttributes { - classBase?: string; - column: RuntimeColumnDescriptor; - onResize?: TableColumnResizeHandler; -} - export const HeaderCell = ({ className: classNameProp, column, diff --git a/vuu-ui/packages/vuu-table/src/index.ts b/vuu-ui/packages/vuu-table/src/index.ts index f9e796339..558444450 100644 --- a/vuu-ui/packages/vuu-table/src/index.ts +++ b/vuu-ui/packages/vuu-table/src/index.ts @@ -1,6 +1,7 @@ export { GroupHeaderCellNext } from "./header-cell"; export * from "./header-cell"; export * from "./Table"; +export * from "./table-cell"; export * from "./table-config"; export * from "./cell-renderers"; export type { RowProps } from "./Row"; diff --git a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css index be1a1fa67..3c0852460 100644 --- a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css +++ b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css @@ -2,27 +2,27 @@ border-right-color: var(--cell-borderColor); border-right-style: solid; border-right-width: 1px; - display: inline-block; - height: 100%; - overflow:hidden; - padding: 0 11px 0 12px; - text-overflow: ellipsis; - vertical-align: top; - } + display: inline-block; + height: 100%; + overflow:hidden; + padding: var(--vuuTableCell-padding, 0 11px 0 12px); + text-overflow: ellipsis; + vertical-align: top; +} - .vuuTableCell-right { +.vuuTableCell-right { text-align: right; - } +} - .vuuTableCell-editable { +.vuuTableCell-editable { display: inline-flex; line-height: 18px; padding-bottom: 1px; padding-top: 1px; text-overflow: unset; - } +} - .vuuTableCell:focus { +.vuuTableCell:focus { outline: var(--vuuTableCell-outline, solid var(--vuu-color-purple-10) 2px); outline-offset: -2px; /** This is to achieve a white background to outline dashes */ diff --git a/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx b/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx index 1d72534ac..ecfd39455 100644 --- a/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx +++ b/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx @@ -2,7 +2,7 @@ import { GroupColumnDescriptor, TableCellProps } from "@finos/vuu-table-types"; import { getGroupValueAndOffset, metadataKeys } from "@finos/vuu-utils"; import { MouseEvent, useCallback } from "react"; import { useCell } from "../useCell"; -import cx from "classnames"; +import cx from "clsx"; import "./TableGroupCell.css"; diff --git a/vuu-ui/packages/vuu-table/src/table-dom-utils.ts b/vuu-ui/packages/vuu-table/src/table-dom-utils.ts index 798b4373a..da10cb990 100644 --- a/vuu-ui/packages/vuu-table/src/table-dom-utils.ts +++ b/vuu-ui/packages/vuu-table/src/table-dom-utils.ts @@ -40,7 +40,7 @@ export function getRowIndex(rowEl?: HTMLElement) { if (rowEl) { const idx: string | null = rowEl.ariaRowIndex; if (idx !== null) { - return parseInt(idx, 10); + return parseInt(idx, 10) - 1; } } return -1; diff --git a/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx b/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx index dc45e0de2..8ec2dfbe8 100644 --- a/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx +++ b/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx @@ -1,13 +1,13 @@ +import { VuuSortType } from "@finos/vuu-protocol-types"; import { ColumnDescriptor, RuntimeColumnDescriptor, + TableColumnResizeHandler, TableConfig, TableHeadings, } from "@finos/vuu-table-types"; import { isGroupColumn, isNotHidden } from "@finos/vuu-utils"; -import cx from "classnames"; -import { VuuSortType } from "packages/vuu-protocol-types"; -import { TableColumnResizeHandler } from "../column-resizing"; +import cx from "clsx"; import { GroupHeaderCellNext, HeaderCell } from "../header-cell"; import { useTableHeader } from "./useTableHeader"; diff --git a/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts b/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts index 12e965742..3792f8d68 100644 --- a/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts +++ b/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts @@ -43,7 +43,11 @@ export const useTableHeader = ({ ? tableConfig.columns.findIndex(ofColumn(nextColumn)) : -1; - onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos)); + if (moveTo > moveFrom && insertPos !== -1) { + onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos - 1)); + } else { + onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos)); + } }, [columns, onMoveColumn, tableConfig.columns] ); diff --git a/vuu-ui/packages/vuu-table/src/useCell.ts b/vuu-ui/packages/vuu-table/src/useCell.ts index dfbad9cf4..b5c23be13 100644 --- a/vuu-ui/packages/vuu-table/src/useCell.ts +++ b/vuu-ui/packages/vuu-table/src/useCell.ts @@ -1,6 +1,6 @@ import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { getColumnStyle } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import { useMemo } from "react"; export const useCell = ( diff --git a/vuu-ui/packages/vuu-table/src/useDataSource.ts b/vuu-ui/packages/vuu-table/src/useDataSource.ts index d02def46b..d220b00a9 100644 --- a/vuu-ui/packages/vuu-table/src/useDataSource.ts +++ b/vuu-ui/packages/vuu-table/src/useDataSource.ts @@ -1,13 +1,13 @@ import { DataSource, + DataSourceRow, DataSourceSubscribedMessage, - isVuuFeatureInvocation, SubscribeCallback, VuuFeatureInvocationMessage, -} from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; +} from "@finos/vuu-data-types"; import { VuuRange } from "@finos/vuu-protocol-types"; import { getFullRange, NULL_RANGE } from "@finos/vuu-utils"; +import { GridAction } from "@finos/vuu-table-types"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { MovingWindow } from "./moving-window"; @@ -21,6 +21,11 @@ export interface DataSourceHookProps { renderBufferSize?: number; } +export const isVuuFeatureInvocation = ( + action: GridAction +): action is VuuFeatureInvocationMessage => + action.type === "vuu-link-created" || action.type === "vuu-link-removed"; + export const useDataSource = ({ dataSource, onFeatureInvocation, diff --git a/vuu-ui/packages/vuu-table/src/useSelection.ts b/vuu-ui/packages/vuu-table/src/useSelection.ts index cd202317b..658d2e81e 100644 --- a/vuu-ui/packages/vuu-table/src/useSelection.ts +++ b/vuu-ui/packages/vuu-table/src/useSelection.ts @@ -1,9 +1,4 @@ -import { - RowClickHandler, - Selection, - SelectionChangeHandler, - TableSelectionModel, -} from "@finos/vuu-table-types"; +import { RowClickHandler, TableSelectionModel } from "@finos/vuu-table-types"; import { deselectItem, dispatchMouseEvent, @@ -11,7 +6,11 @@ import { metadataKeys, selectItem, } from "@finos/vuu-utils"; -import { DataSourceRow } from "packages/vuu-data-types"; +import { + DataSourceRow, + Selection, + SelectionChangeHandler, +} from "@finos/vuu-data-types"; import { KeyboardEvent, KeyboardEventHandler, diff --git a/vuu-ui/packages/vuu-table/src/useTable.ts b/vuu-ui/packages/vuu-table/src/useTable.ts index 599ee316e..b336aa318 100644 --- a/vuu-ui/packages/vuu-table/src/useTable.ts +++ b/vuu-ui/packages/vuu-table/src/useTable.ts @@ -1,25 +1,20 @@ import { DataSourceConfig, + DataSourceRow, DataSourceSubscribedMessage, - JsonDataSource, -} from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; + SelectionChangeHandler, +} from "@finos/vuu-data-types"; import { ColumnDescriptor, DataCellEditHandler, RowClickHandler, RuntimeColumnDescriptor, - SelectionChangeHandler, + TableColumnResizeHandler, TableConfig, TableSelectionModel, } from "@finos/vuu-table-types"; -import { - MeasuredProps, - MeasuredSize, - useLayoutEffectSkipFirst, -} from "@finos/vuu-layout"; +import { MeasuredProps, MeasuredSize } from "@finos/vuu-layout"; import { VuuRange, VuuSortType } from "@finos/vuu-protocol-types"; -import { useTableAndColumnSettings } from "@finos/vuu-table-extras"; import { DragStartHandler, useDragDropNext as useDragDrop, @@ -32,6 +27,7 @@ import { isValidNumber, metadataKeys, updateColumn, + useLayoutEffectSkipFirst, } from "@finos/vuu-utils"; import { FocusEvent, @@ -42,7 +38,6 @@ import { useMemo, useState, } from "react"; -import { TableColumnResizeHandler } from "./column-resizing"; import { buildContextMenuDescriptors, useHandleTableContextMenu, @@ -66,6 +61,7 @@ import { import { useTableScroll } from "./useTableScroll"; import { useTableViewport } from "./useTableViewport"; import { useVirtualViewport } from "./useVirtualViewport"; +import { useTableAndColumnSettings } from "./useTableAndColumnSettings"; const stripInternalProperties = (tableConfig: TableConfig): TableConfig => { return tableConfig; @@ -249,6 +245,7 @@ export const useTable = ({ const { data, dataRef, getSelectedRows, range, setRange } = useDataSource({ dataSource, + // We need to factor this out of Table onFeatureInvocation, renderBufferSize, onSizeChange: onDataRowcountChange, @@ -436,11 +433,11 @@ export const useTable = ({ const key = row[KEY]; if (row[IS_EXPANDED]) { - (dataSource as JsonDataSource).closeTreeNode(key, true); + dataSource.closeTreeNode(key, true); if (isJson) { const idx = columns.indexOf(column); - const rows = (dataSource as JsonDataSource).getRowsAtDepth(idx + 1); - if (!rows.some((row) => row[IS_EXPANDED] || row[IS_LEAF])) { + const rows = dataSource.getRowsAtDepth?.(idx + 1); + if (rows && !rows.some((row) => row[IS_EXPANDED] || row[IS_LEAF])) { dispatchColumnAction({ type: "hideColumns", columns: columns.slice(idx + 2), @@ -450,10 +447,10 @@ export const useTable = ({ } else { dataSource.openTreeNode(key); if (isJson) { - const childRows = (dataSource as JsonDataSource).getChildRows(key); + const childRows = dataSource.getChildRows?.(key); const idx = columns.indexOf(column) + 1; const columnsToShow = [columns[idx]]; - if (childRows.some((row) => row[IS_LEAF])) { + if (childRows && childRows.some((row) => row[IS_LEAF])) { columnsToShow.push(columns[idx + 1]); } if (columnsToShow.some((col) => col.hidden)) { @@ -606,6 +603,9 @@ export const useTable = ({ const onMoveColumn = useCallback( (columns: ColumnDescriptor[]) => { + console.log(`useTable onMoveColumn`, { + columns, + }); const newTableConfig = { ...tableConfig, columns, diff --git a/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts b/vuu-ui/packages/vuu-table/src/useTableAndColumnSettings.ts similarity index 95% rename from vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts rename to vuu-ui/packages/vuu-table/src/useTableAndColumnSettings.ts index 17229d727..8c7ad6ba7 100644 --- a/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts +++ b/vuu-ui/packages/vuu-table/src/useTableAndColumnSettings.ts @@ -1,13 +1,14 @@ -import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data"; -import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types"; +import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data-types"; import { useLayoutProviderDispatch } from "@finos/vuu-layout"; import { + ColumnDescriptor, ColumnSettingsProps, + TableConfig, TableSettingsProps, -} from "@finos/vuu-table-extras"; -import { ColumnActionColumnSettings } from "@finos/vuu-table"; +} from "@finos/vuu-table-types"; import { getCalculatedColumnType } from "@finos/vuu-utils"; import { useCallback, useRef, useState } from "react"; +import { ColumnActionColumnSettings } from "./useTableModel"; export interface TableAndColumnSettingsHookProps { availableColumns: SchemaColumn[]; diff --git a/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts b/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts index 6c715ffdd..24c6a0a38 100644 --- a/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts +++ b/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts @@ -1,5 +1,4 @@ -import { DataSource } from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; +import { DataSource, DataSourceRow } from "@finos/vuu-data-types"; import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { useContextMenu as usePopupContextMenu } from "@finos/vuu-popups"; import { buildColumnMap } from "@finos/vuu-utils"; diff --git a/vuu-ui/packages/vuu-table/src/useTableModel.ts b/vuu-ui/packages/vuu-table/src/useTableModel.ts index de734cf38..d20e8fcba 100644 --- a/vuu-ui/packages/vuu-table/src/useTableModel.ts +++ b/vuu-ui/packages/vuu-table/src/useTableModel.ts @@ -1,7 +1,8 @@ import { ColumnDescriptor, - RuntimeColumnDescriptor, PinLocation, + ResizePhase, + RuntimeColumnDescriptor, TableAttributes, TableConfig, TableHeadings, @@ -11,6 +12,8 @@ import { applyGroupByToColumns, applySortToColumns, getCellRenderer, + getColumnHeaderContentRenderer, + getColumnHeaderLabelRenderer, getColumnLabel, getTableHeadings, getValueFormatter, @@ -26,8 +29,11 @@ import { subscribedOnly, } from "@finos/vuu-utils"; -import { DataSource, DataSourceConfig } from "@finos/vuu-data"; -import { TableSchema } from "@finos/vuu-data/src/message-utils"; +import { + DataSource, + DataSourceConfig, + TableSchema, +} from "@finos/vuu-data-types"; import { VuuColumnDataType, VuuTable } from "@finos/vuu-protocol-types"; import { buildValidationChecker } from "@finos/vuu-ui-controls"; import { Reducer, useReducer } from "react"; @@ -108,8 +114,6 @@ export interface ColumnActionPin { pin?: PinLocation; } -export type ResizePhase = "begin" | "resize" | "end"; - export interface ColumnActionResize { type: "resizeColumn"; column: RuntimeColumnDescriptor; @@ -240,7 +244,6 @@ type InitialConfig = { function init({ dataSource, tableConfig }: InitialConfig): InternalTableModel { const { columns, ...tableAttributes } = tableConfig; - console.log(JSON.stringify(tableAttributes, null, 2)); const { config: dataSourceConfig, tableSchema } = dataSource; const runtimeColumns = columns .filter(subscribedOnly(dataSourceConfig?.columns)) @@ -297,12 +300,12 @@ const columnDescriptorToRuntimeColumDescriptor = ...rest } = column; - const runtimeColumnWithDefaults = { + const runtimeColumnWithDefaults: RuntimeColumnDescriptor = { ...rest, align, CellRenderer: getCellRenderer(column), - HeaderCellLabelRenderer: getCellRenderer(column, "col-label"), - HeaderCellContentRenderer: getCellRenderer(column, "col-content"), + HeaderCellContentRenderer: getColumnHeaderContentRenderer(column), + HeaderCellLabelRenderer: getColumnHeaderLabelRenderer(column), clientSideEditValidationCheck: hasValidationRules(column.type) ? buildValidationChecker(column.type.renderer.rules) : undefined, diff --git a/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts b/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts index c57a40f75..b95486ccf 100644 --- a/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts +++ b/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts @@ -2,7 +2,7 @@ import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { VuuRange } from "@finos/vuu-protocol-types"; import { RowAtPositionFunc } from "@finos/vuu-utils"; import { useCallback, useEffect, useRef } from "react"; -import { ViewportMeasurements } from "@finos/vuu-table"; +import { ViewportMeasurements } from "./useTableViewport"; export interface VirtualViewportHookProps { columns: RuntimeColumnDescriptor[]; @@ -12,13 +12,12 @@ export interface VirtualViewportHookProps { } export const useVirtualViewport = ({ - columns, getRowAtPosition, setRange, viewportMeasurements, }: VirtualViewportHookProps) => { const firstRowRef = useRef(0); - const { contentWidth, rowCount: viewportRowCount } = viewportMeasurements; + const { rowCount: viewportRowCount } = viewportMeasurements; const handleVerticalScroll = useCallback( (scrollTop: number) => { diff --git a/vuu-ui/packages/vuu-theme/css/components/checkbox.css b/vuu-ui/packages/vuu-theme/css/components/checkbox.css index 68d813b98..a1c3cf0a5 100644 --- a/vuu-ui/packages/vuu-theme/css/components/checkbox.css +++ b/vuu-ui/packages/vuu-theme/css/components/checkbox.css @@ -42,8 +42,8 @@ background-color: var(--vuu-icon-color); left: var(--vuu-icon-left, auto); height: var(--vuu-icon-height, var(--vuu-icon-size, 12px)); + mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size); -webkit-mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size); - mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; position: absolute; diff --git a/vuu-ui/packages/vuu-theme/css/components/switch.css b/vuu-ui/packages/vuu-theme/css/components/switch.css index c40cde19a..e032d64e8 100644 --- a/vuu-ui/packages/vuu-theme/css/components/switch.css +++ b/vuu-ui/packages/vuu-theme/css/components/switch.css @@ -1,7 +1,6 @@ .saltSwitch { --switch-color: var(--vuu-color-gray-45); --vuu-icon-left: -1px; - } .saltSwitch-track { @@ -13,7 +12,7 @@ width: 26px; } -.saltSwitch:hover .saltSwitch-track { +.saltSwitch:not(.saltSwitch-disabled):hover .saltSwitch-track { --switch-color: var(--vuu-color-pink-10); } @@ -30,6 +29,10 @@ --switch-color: var(--vuu-color-purple-10); } +.saltSwitch-disabled { + --switch-color: var(--vuu-color-gray-30); +} + .saltSwitch-checked .saltSwitch-thumb, .saltSwitch-checked:hover .saltSwitch-thumb { background-color: white; @@ -42,8 +45,8 @@ content: ""; left: var(--vuu-icon-left, auto); height: var(--vuu-icon-height, var(--vuu-icon-size, 12px)); + mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size); -webkit-mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size); - mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size); mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; position: absolute; diff --git a/vuu-ui/packages/vuu-theme/css/palette/neutral.css b/vuu-ui/packages/vuu-theme/css/palette/neutral.css index d5ed43163..db95dd59c 100644 --- a/vuu-ui/packages/vuu-theme/css/palette/neutral.css +++ b/vuu-ui/packages/vuu-theme/css/palette/neutral.css @@ -1,6 +1,6 @@ .vuu-theme[data-mode="light"] { --salt-palette-neutral-primary-background: var(--salt-color-white); - --salt-palette-neutral-primary-background-disabled: var(--salt-color-white-fade-background); + --salt-palette-neutral-primary-background-disabled: var(--vuu-color-gray-30); --salt-palette-neutral-primary-background-readonly: var(--salt-color-white-fade-background-readonly); --salt-palette-neutral-primary-foreground: var(--vuu-color-gray-80); --salt-palette-neutral-primary-foreground-disabled: var(--salt-color-gray-900-fade-foreground); diff --git a/vuu-ui/packages/vuu-ui-controls/package.json b/vuu-ui/packages/vuu-ui-controls/package.json index 9bbf380eb..02ccb0c13 100644 --- a/vuu-ui/packages/vuu-ui-controls/package.json +++ b/vuu-ui/packages/vuu-ui-controls/package.json @@ -10,8 +10,7 @@ "type-defs": "node ../../scripts/build-type-defs.mjs" }, "dependencies": { - "@salt-ds/core": "1.8.0", - "@finos/vuu-data": "0.0.26", + "@salt-ds/core": "1.13.2", "@finos/vuu-data-types": "0.0.26", "@finos/vuu-table-types": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -20,8 +19,9 @@ "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" - } + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" + }, + "sideEffects": false } diff --git a/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx b/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx index 84618f28b..dd328424d 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx @@ -1,4 +1,4 @@ -import { useId } from "@finos/vuu-layout"; +import { useId } from "@finos/vuu-utils"; import { Input, InputProps } from "@salt-ds/core"; import { ForwardedRef, @@ -16,8 +16,8 @@ import { } from "../common-hooks"; import { DropdownBase, DropdownBaseProps } from "../dropdown"; import { List, ListProps } from "../list"; -import { useCombobox } from "./useCombobox"; import { ChevronIcon } from "../list/ChevronIcon"; +import { useCombobox } from "./useCombobox"; //TODO why do we need onSelect from input ? export interface ComboBoxProps< diff --git a/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts b/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts index a5063293b..10bb9aa73 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts @@ -1,5 +1,5 @@ +import { useLayoutEffectSkipFirst } from "@finos/vuu-utils"; import { InputProps, useControlled } from "@salt-ds/core"; -import { useLayoutEffectSkipFirst } from "@finos/vuu-layout"; import { ChangeEvent, FocusEvent, @@ -107,7 +107,7 @@ export const useCombobox = ({ }: ComboboxHookProps): ComboboxHookResult => { const isMultiSelect = isMultiSelection(selectionStrategy); - const { data, setFilterPattern } = collectionHook; + const { setFilterPattern } = collectionHook; const setHighlightedIndexRef = useRef void)>(null); // used to track multi selection const selectedRef = useRef(isMultiSelect ? [] : null); diff --git a/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts b/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts index fe088d564..9e5bb6999 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts @@ -62,11 +62,6 @@ const getTargetSize = ( } }; -const isScrollAttribute = { - scrollHeight: true, - scrollWidth: true, -}; - // TODO should we make this create-on-demand const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => { for (const entry of entries) { @@ -78,7 +73,7 @@ const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => { contentBoxSize; const { onResize, measurements } = observedTarget; let sizeChanged = false; - for (let [dimension, size] of Object.entries(measurements)) { + for (const [dimension, size] of Object.entries(measurements)) { const newSize = getTargetSize( target as HTMLElement, { height, width, contentHeight, contentWidth }, diff --git a/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx b/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx index 9f9de984c..8dd90fd7a 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx @@ -1,10 +1,10 @@ import { Button, ButtonProps } from "@salt-ds/core"; -import cx from "classnames"; -import { CommitResponse } from "packages/vuu-table-types"; -import { +import cx from "clsx"; +import type { CommitResponse } from "@finos/vuu-table-types"; +import type { VuuColumnDataType, VuuRowDataItemType, -} from "packages/vuu-protocol-types"; +} from "@finos/vuu-protocol-types"; import { ForwardedRef, forwardRef, SyntheticEvent, useCallback } from "react"; const classBase = "vuuCycleStateButton"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx index 1e8d3be34..75a79cd1a 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx @@ -1,5 +1,5 @@ import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { CSSProperties, forwardRef, diff --git a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts index a39d84e65..2267fde99 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts @@ -1,4 +1,6 @@ export * from "./dragDropTypesNext"; export * from "./DragDropProvider"; +export * from "./DragDropState"; export * from "./useDragDropNext"; export * from "./drop-target-utils"; +export * from "./useGlobalDragDrop"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx b/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx index fa04c1bca..f6ff75c0c 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx @@ -8,7 +8,7 @@ import { useRef, } from "react"; -import { useId } from "@finos/vuu-layout"; +import { useId } from "@finos/vuu-utils"; import { CollectionProvider, itemToString as defaultItemToString, @@ -17,10 +17,10 @@ import { useCollectionItems, } from "../common-hooks"; import { List, ListProps } from "../list"; +import { forwardCallbackProps } from "../utils"; import { DropdownBase, MaybeChildProps } from "./DropdownBase"; import { DropdownButton } from "./DropdownButton"; import { DropdownBaseProps } from "./dropdownTypes"; -import { forwardCallbackProps } from "../utils"; import { useDropdown } from "./useDropdown"; export interface DropdownProps< diff --git a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx index 3e932f2af..bb71b5655 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx @@ -1,11 +1,11 @@ -import cx from "classnames"; +import { PopupComponent as Popup, Portal } from "@finos/vuu-popups"; +import { useId } from "@finos/vuu-utils"; import { useForkRef } from "@salt-ds/core"; +import cx from "clsx"; import { Children, cloneElement, forwardRef, useRef } from "react"; import { forwardCallbackProps } from "../utils"; import { DropdownBaseProps } from "./dropdownTypes"; import { useDropdownBase } from "./useDropdownBase"; -import { useId } from "@finos/vuu-layout"; -import { PopupComponent as Popup, Portal } from "@finos/vuu-popups"; import "./Dropdown.css"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx index 6ea5fc8b8..5c7b62434 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx @@ -1,5 +1,5 @@ import { Button, ButtonProps } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { AriaAttributes, ForwardedRef, forwardRef } from "react"; import "./DropdownButton.css"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx b/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx index f7cace02f..67f55d2a3 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import { ChangeEvent, KeyboardEvent, diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts b/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts index 274905063..1e49c84bf 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts @@ -1,5 +1,5 @@ import { DataItemCommitHandler } from "@finos/vuu-table-types"; -import { useLayoutEffectSkipFirst } from "@finos/vuu-layout"; +import { useLayoutEffectSkipFirst } from "@finos/vuu-utils"; import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; import { dispatchCustomEvent } from "@finos/vuu-utils"; import { diff --git a/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx b/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx index 54fa022bd..ee9abafdd 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx @@ -1,6 +1,6 @@ -import { VuuInput, VuuInputProps } from "@finos/vuu-ui-controls"; -import cx from "classnames"; +import cx from "clsx"; import { ForwardedRef, forwardRef } from "react"; +import { VuuInput, VuuInputProps } from "../vuu-input"; import "./ExpandoInput.css"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx b/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx index 85eda99c2..889a5921f 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx @@ -1,16 +1,16 @@ -import { CheckboxIcon } from "@finos/vuu-ui-controls/src/list/CheckboxIcon"; +import { CheckboxIcon } from "../list/CheckboxIcon"; import "./Checkbox.css"; type CheckboxProps = { - onToggle: () => void, - className?: string, - checked: boolean, - label: string -} + onToggle: () => void; + className?: string; + checked: boolean; + label: string; +}; export const Checkbox = (props: CheckboxProps): JSX.Element => { - const {onToggle, checked, label} = props; + const { onToggle, checked, label } = props; return (
{ {label}
- ) -} + ); +}; diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx index 5398cefe9..503cefc45 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx @@ -1,18 +1,20 @@ -import { TableSchema } from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; -import { useId } from "@finos/vuu-layout"; +import { DataSourceRow, TableSchema } from "@finos/vuu-data-types"; import { Table, TableProps, TableRowSelectHandler } from "@finos/vuu-table"; -import { ColumnMap } from "@finos/vuu-utils"; +import { ColumnMap, useId } from "@finos/vuu-utils"; import { Input } from "@salt-ds/core"; import { ForwardedRef, forwardRef, HTMLAttributes, useMemo } from "react"; import { DropdownBase, OpenChangeHandler } from "../dropdown"; -import "./SearchCell"; +import { SearchCell } from "./SearchCell"; import { useInstrumentPicker } from "./useInstrumentPicker"; import "./InstrumentPicker.css"; const classBase = "vuuInstrumentPicker"; +if (typeof SearchCell !== "function") { + console.warn("Instrument Picker: SearchCell module not loaded "); +} + export interface InstrumentPickerProps extends Omit, "onSelect"> { TableProps: Pick; diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts index 4fe080729..9dafe4575 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts @@ -1,7 +1,10 @@ //TODO stansardise this -import { DataSource, SubscribeCallback } from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; +import { + DataSource, + DataSourceRow, + SubscribeCallback, +} from "@finos/vuu-data-types"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { MovingWindow } from "./moving-window"; export interface DataSourceHookProps { diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts index 37f03a6ba..309bc2508 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts @@ -1,5 +1,4 @@ -import { DataSource } from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; +import { DataSource, DataSourceRow } from "@finos/vuu-data-types"; import { ColumnDescriptor } from "@finos/vuu-table-types"; import { TableRowSelectHandler, diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx index f38449ad4..20a885b01 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx @@ -1,4 +1,4 @@ -import { DataSource } from "@finos/vuu-data"; +import { DataSource } from "@finos/vuu-data-types"; import { TableConfig } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-layout"; @@ -8,16 +8,19 @@ import { useControlledTableNavigation, } from "@finos/vuu-table"; import { Input } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes, RefCallback, useCallback } from "react"; -import "./SearchCell"; +import { SearchCell } from "./SearchCell"; import "./InstrumentSearch.css"; -import { VuuTable } from "packages/vuu-protocol-types"; import { useInstrumentSearch } from "./useInstrumentSearch"; const classBase = "vuuInstrumentSearch"; +if (typeof SearchCell !== "function") { + console.warn("Instrument Search: SearchCell module not loaded "); +} + const defaultTableConfig: TableConfig = { columns: [ { name: "bbg", hidden: true }, @@ -38,10 +41,9 @@ const defaultTableConfig: TableConfig = { export interface InstrumentSearchProps extends HTMLAttributes { TableProps?: Partial; autoFocus?: boolean; - dataSource?: DataSource; + dataSource: DataSource; placeHolder?: string; searchColumns?: string[]; - table?: VuuTable; } const searchIcon = ; @@ -53,13 +55,11 @@ export const InstrumentSearch = ({ dataSource: dataSourceProp, placeHolder, searchColumns, - table, ...htmlAttributes }: InstrumentSearchProps) => { const { dataSource, onChange, searchState } = useInstrumentSearch({ dataSource: dataSourceProp, searchColumns, - table, }); const { highlightedIndexRef, onHighlight, onKeyDown, tableRef } = diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts index 4fe080729..9dafe4575 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts @@ -1,7 +1,10 @@ //TODO stansardise this -import { DataSource, SubscribeCallback } from "@finos/vuu-data"; -import { DataSourceRow } from "@finos/vuu-data-types"; +import { + DataSource, + DataSourceRow, + SubscribeCallback, +} from "@finos/vuu-data-types"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { MovingWindow } from "./moving-window"; export interface DataSourceHookProps { diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts index 3f90ca8e0..237ba5557 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts @@ -1,25 +1,15 @@ -import { DataSource, RemoteDataSource } from "@finos/vuu-data"; -import { getVuuTableSchema } from "@finos/vuu-data-react"; -import { useViewContext } from "@finos/vuu-layout"; import { FormEventHandler, useCallback, useMemo, useState } from "react"; import { InstrumentSearchProps } from "./InstrumentSearch"; export interface InstrumentSearchHookProps - extends Pick< - InstrumentSearchProps, - "dataSource" | "searchColumns" | "table" - > { + extends Pick { label?: string; } export const useInstrumentSearch = ({ - dataSource: dataSourceProp, + dataSource, searchColumns = ["description"], - table, }: InstrumentSearchHookProps) => { - const [dataSource, setDataSource] = useState(dataSourceProp); - const { loadSession, saveSession } = useViewContext(); - const [searchState, setSearchState] = useState<{ searchText: string; filter: string; @@ -31,32 +21,6 @@ export const useInstrumentSearch = ({ [searchColumns] ); - useMemo(() => { - if (dataSourceProp === undefined) { - if (table) { - const sessionKey = `instrument-search-${table.module}-${table.table}`; - const dataSource = loadSession?.(sessionKey) as DataSource; - if (dataSource) { - setDataSource(dataSource); - } else { - getVuuTableSchema(table).then((tableSchema) => { - const newDataSource = new RemoteDataSource({ - columns: tableSchema.columns.map((col) => col.name), - // sort: { sortDefs: [{ column: "description", sortType: "A" }] }, - table: tableSchema.table, - }); - setDataSource(newDataSource); - saveSession?.(newDataSource, sessionKey); - }); - } - } else { - throw Error( - `useInstrumentSearch, if dataSource ismnot provided as prop, Vuu table must be provided` - ); - } - } - }, [dataSourceProp, loadSession, saveSession, table]); - const handleChange = useCallback( (evt) => { const { value } = evt.target as HTMLInputElement; diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx index 4521b67e6..ab0701a16 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx @@ -1,7 +1,7 @@ // TODO why do we need explicit React import - its not needed anywhere else // but we see a 'React is not defined' issue in showcase without it import React, { HTMLAttributes } from "react"; -import cx from "classnames"; +import cx from "clsx"; import "./CheckboxIcon.css"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx index 25e060d61..851849b80 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import { HTMLAttributes } from "react"; import "./ChevronIcon.css"; @@ -13,7 +13,5 @@ interface ChevronProps extends HTMLAttributes { export const ChevronIcon = (props: ChevronProps) => { const { direction, ...htmlAttributes } = props; - return ( - - ) + return ; }; diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx index 18e56040e..ad2b5d9a2 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx @@ -1,6 +1,7 @@ -import { MeasuredContainer, MeasuredSize, useId } from "@finos/vuu-layout"; +import { MeasuredContainer, MeasuredSize } from "@finos/vuu-layout"; +import { useId } from "@finos/vuu-utils"; import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { cloneElement, ForwardedRef, @@ -11,18 +12,18 @@ import { useRef, useState, } from "react"; -import { - isSelected, - LIST_FOCUS_VISIBLE, - useCollectionItems, - useImperativeScrollingAPI, -} from "./common-hooks"; import { CollectionIndexer, CollectionItem, itemToString as defaultItemToString, SelectionStrategy, } from "../common-hooks"; +import { + isSelected, + LIST_FOCUS_VISIBLE, + useCollectionItems, + useImperativeScrollingAPI, +} from "./common-hooks"; import { ListItem as DefaultListItem, ListItemProxy } from "./ListItem"; import { ListItemProps, ListProps } from "./listTypes"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx index cafbbfbc2..745071a93 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx @@ -1,5 +1,5 @@ import { ForwardedRef, forwardRef, HTMLAttributes } from "react"; -import cx from "classnames"; +import cx from "clsx"; import { ListItemProps, ListItemType } from "./listTypes"; import { Highlighter } from "./Highlighter"; import { CheckboxIcon } from "./CheckboxIcon"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx index db2423404..0b514a7ba 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx @@ -1,13 +1,10 @@ -import cx from "classnames"; +import cx from "clsx"; import "./RadioIcon.css"; const classBase = "vuuRadioIcon"; -export const RadioIcon = ({ - checked = false, - ...htmlAttributes -}) => ( +export const RadioIcon = ({ checked = false, ...htmlAttributes }) => ( ) => Array.isArray(item.childNodes); // TODO how do we determine this and where does this function belong = in the collectionHook ? -const canSelectItem = (item: CollectionItem) => true; +const canSelectItem = (_: CollectionItem) => true; const toggleIconClicked = (el: HTMLElement) => { const closestToggle = el.closest( diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts b/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts index 68782b4a3..511005e04 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts @@ -154,7 +154,7 @@ export const sourceItems = ( ]; } else { return source.map( - (item: { description?: string; expanded?: boolean }, index) => + (item: { description?: string; expanded?: boolean }) => ({ childNodes: sourceItems( (item as unknown as SourceGroup).childNodes, diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts b/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts index cfe5d99cd..4e34c13ac 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts @@ -1,4 +1,4 @@ -import { useLayoutEffectSkipFirst } from "@finos/vuu-layout"; +import { useLayoutEffectSkipFirst } from "@finos/vuu-utils"; import { KeyboardEvent, MouseEvent, diff --git a/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx b/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx index 454b13c67..8d9cd57ae 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx @@ -5,7 +5,7 @@ import { valueChangeDirection, } from "@finos/vuu-utils"; import { HTMLAttributes, memo, useMemo, useRef } from "react"; -import cx from "classnames"; +import cx from "clsx"; const classBase = "vuuPriceTicker"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx index dc6276f79..195d00d2d 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx @@ -1,6 +1,6 @@ // TODO close button needs to be a button. Hence tab needs to include 2 buttons import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { MenuActionHandler } from "@finos/vuu-data-types"; import { FocusEvent, diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx index e4d1bfe94..41e4a9703 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx @@ -5,7 +5,7 @@ import { MenuBuilder, } from "@finos/vuu-data-types"; import { useMemo } from "react"; -import cx from "classnames"; +import cx from "clsx"; import { closeCommand, MenuOptions, renameCommand } from "./TabMenuOptions"; import "./TabMenu.css"; @@ -57,7 +57,13 @@ export const TabMenu = ({ tabIndex: index, }, ], - [allowClose, allowRename, controlledComponentId, index] + [ + allowClose, + allowRename, + controlledComponentId, + controlledComponentTitle, + index, + ] ); return ( @@ -69,6 +75,7 @@ export const TabMenu = ({ menuOptions={menuOptions} onMenuClose={onMenuClose} tabIndex={-1} + aria-label="context menu" /> ); }; diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx index 1ebb1a1f8..fa84d4214 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx @@ -1,6 +1,7 @@ -import { asReactElements, OverflowContainer, useId } from "@finos/vuu-layout"; +import { asReactElements, OverflowContainer } from "@finos/vuu-layout"; +import { useId } from "@finos/vuu-utils"; import { Button } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import React, { useMemo, useRef } from "react"; import { TabProps, TabstripProps } from "./TabsTypes"; import { useTabstrip } from "./useTabstrip"; @@ -142,6 +143,7 @@ export const Tabstrip = ({ overflowIcon="more-horiz" ref={rootRef} style={style} + role="tablist" > {tabs} diff --git a/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx b/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx index e03b44012..ceb61922b 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx @@ -1,5 +1,5 @@ import { useForkRef, useIdMemo as useId } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { ForwardedRef, forwardRef, diff --git a/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx b/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx index 00c3444d6..cd1ab740e 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx @@ -1,7 +1,8 @@ +import { Tooltip, useTooltip } from "@finos/vuu-popups"; import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; -import { isValidNumber } from "@finos/vuu-utils"; +import { isValidNumber, useId } from "@finos/vuu-utils"; import { Input, InputProps } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { FocusEventHandler, ForwardedRef, @@ -11,8 +12,6 @@ import { SyntheticEvent, useCallback, } from "react"; -import { Tooltip, useTooltip } from "@finos/vuu-popups"; -import { useId } from "@finos/vuu-layout"; import "./VuuInput.css"; diff --git a/vuu-ui/packages/vuu-utils/package.json b/vuu-ui/packages/vuu-utils/package.json index 9302ed323..6c16269d7 100644 --- a/vuu-ui/packages/vuu-utils/package.json +++ b/vuu-ui/packages/vuu-utils/package.json @@ -11,12 +11,14 @@ "type-defs": "node ../../scripts/build-type-defs.mjs" }, "devDependencies": { + "@finos/vuu-data-types": "0.0.26", "@finos/vuu-table-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-protocol-types": "0.0.26" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" - } + "react": ">=17.0.2", + "react-dom": ">=17.0.2" + }, + "sideEffects": false } diff --git a/vuu-ui/packages/vuu-shell/src/theme-provider/ThemeProvider.tsx b/vuu-ui/packages/vuu-utils/src/ThemeProvider.tsx similarity index 97% rename from vuu-ui/packages/vuu-shell/src/theme-provider/ThemeProvider.tsx rename to vuu-ui/packages/vuu-utils/src/ThemeProvider.tsx index 660e95bc7..10a322d72 100644 --- a/vuu-ui/packages/vuu-shell/src/theme-provider/ThemeProvider.tsx +++ b/vuu-ui/packages/vuu-utils/src/ThemeProvider.tsx @@ -6,7 +6,7 @@ import React, { cloneElement, useContext, } from "react"; -import cx from "classnames"; +import cx from "clsx"; export const DEFAULT_DENSITY: Density = "medium"; export const DEFAULT_THEME = "salt-theme"; @@ -83,7 +83,7 @@ const createThemedChildren = ( } else { console.warn( `\nThemeProvider can only apply CSS classes for theming to a single nested child element of the ThemeProvider. - Wrap elements with a single container` + Wrap elements with a single container` ); return children; } diff --git a/vuu-ui/packages/vuu-utils/src/column-utils.ts b/vuu-ui/packages/vuu-utils/src/column-utils.ts index f61cddd1e..2e9ccb66a 100644 --- a/vuu-ui/packages/vuu-utils/src/column-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/column-utils.ts @@ -1,34 +1,39 @@ -import type { SchemaColumn, TableSchema } from "@finos/vuu-data"; -import type { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; +import type { + DataSourceFilter, + DataSourceRow, + SchemaColumn, + TableSchema, +} from "@finos/vuu-data-types"; +import type { Filter, MultiClauseFilter } from "@finos/vuu-filter-types"; +import type { + VuuAggregation, + VuuAggType, + VuuColumnDataType, + VuuDataRow, + VuuGroupBy, + VuuRowRecord, + VuuSort, +} from "@finos/vuu-protocol-types"; import type { ColumnAlignment, ColumnDescriptor, ColumnType, ColumnTypeDescriptor, + ColumnTypeFormatting, ColumnTypeRendering, + ColumnTypeSimple, ColumnTypeWithValidationRules, + DefaultColumnConfiguration, GroupColumnDescriptor, - RuntimeColumnDescriptor, + LookupRenderer, MappedValueTypeRenderer, PinLocation, + RuntimeColumnDescriptor, TableHeading, TableHeadings, - ColumnTypeFormatting, - LookupRenderer, ValueListRenderer, - DateTimeColumnTypeSimple, + DateTimeColumnDescriptor, } from "@finos/vuu-table-types"; -import type { Filter, MultiClauseFilter } from "@finos/vuu-filter-types"; -import type { - VuuAggregation, - VuuAggType, - VuuColumnDataType, - VuuDataRow, - VuuGroupBy, - VuuRowRecord, - VuuSort, -} from "@finos/vuu-protocol-types"; -import { DefaultColumnConfiguration } from "@finos/vuu-shell"; import type { CSSProperties } from "react"; import { moveItem } from "./array-utils"; import { isFilterClause, isMultiClauseFilter } from "./filter-utils"; @@ -127,22 +132,11 @@ export const isNumericColumn = ({ serverDataType, type }: ColumnDescriptor) => { return false; }; -type DateTimeColumnType = - | DateTimeColumnTypeSimple - | (Omit & { name: DateTimeColumnTypeSimple }); - -export type DateTimeColumnDescriptor = Omit & { - type: DateTimeColumnType; -}; - -export const isDateColumn = ({ type }: ColumnDescriptor) => - (isTypeDescriptor(type) ? type.name : type) === "date"; -export const isTimeColumn = ({ type }: ColumnDescriptor) => - (isTypeDescriptor(type) ? type.name : type) === "time"; export const isDateTimeColumn = ( column: ColumnDescriptor ): column is DateTimeColumnDescriptor => - isDateColumn(column) || isTimeColumn(column); + (isTypeDescriptor(column.type) ? column.type.name : column.type) === + "date/time"; export const isPinned = (column: ColumnDescriptor) => typeof column.pin === "string"; @@ -161,21 +155,6 @@ export const toColumnDescriptor = (name: string): ColumnDescriptor => ({ name, }); -export const isSimpleColumnType = (value: unknown): value is ColumnTypeSimple => - typeof value === "string" && - ["string", "number", "boolean", "json", "date", "time", "checkbox"].includes( - value - ); - -export declare type ColumnTypeSimple = - | "string" - | "number" - | "boolean" - | "json" - | "date" - | "time" - | "checkbox"; - /** * */ @@ -773,56 +752,41 @@ export const getDefaultColumnType = ( } }; -export const updateColumnType = ( +export const updateColumnFormatting = < + T extends ColumnDescriptor = ColumnDescriptor +>( column: T, formatting: ColumnTypeFormatting ): T => { const { serverDataType, type = getDefaultColumnType(serverDataType) } = column; - if (typeof type === "string" || type === undefined) { - return { - ...column, - type: { - name: type, - formatting, - }, - } as T; + if (isTypeDescriptor(type)) { + return { ...column, type: { ...type, formatting } }; } else { - return { - ...column, - type: { - ...type, - formatting, - }, - } as T; + return { ...column, type: { name: type, formatting } }; } }; +export function updateColumnType( + column: T, + type: ColumnTypeSimple +): T { + return isTypeDescriptor(column.type) + ? { ...column, type: { ...column.type, name: type } } + : { ...column, type }; +} + export const updateColumnRenderProps = < T extends ColumnDescriptor = ColumnDescriptor >( column: T, renderer: ColumnTypeRendering ): T => { - const { serverDataType, type } = column; - if (type === undefined) { - return { - ...column, - type: { - name: getDefaultColumnType(serverDataType), - renderer, - }, - }; - } else if (isSimpleColumnType(type)) { - return { - ...column, - type: { - name: type, - renderer, - }, - }; - } else { + const { serverDataType, type = getDefaultColumnType(serverDataType) } = + column; + + if (isTypeDescriptor(type)) { return { ...column, type: { @@ -831,6 +795,8 @@ export const updateColumnRenderProps = < renderer, }, }; + } else { + return { ...column, type: { name: type, renderer } }; } }; diff --git a/vuu-ui/packages/vuu-utils/src/component-registry.ts b/vuu-ui/packages/vuu-utils/src/component-registry.ts index cafc01cf7..5cc986061 100644 --- a/vuu-ui/packages/vuu-utils/src/component-registry.ts +++ b/vuu-ui/packages/vuu-utils/src/component-registry.ts @@ -4,6 +4,7 @@ import { ColumnDescriptorCustomRenderer, ColumnTypeRendering, EditValidationRule, + HeaderCellProps, TableCellRendererProps, } from "@finos/vuu-table-types"; import { @@ -11,7 +12,6 @@ import { VuuRowDataItemType, } from "@finos/vuu-protocol-types"; import { isTypeDescriptor, isColumnTypeRenderer } from "./column-utils"; -import { HeaderCellProps } from "@finos/vuu-table"; export interface CellConfigPanelProps extends HTMLAttributes { onConfigChange: () => void; @@ -33,6 +33,7 @@ export interface ConfigurationEditorProps { export type ConfigEditorComponent = FC; const cellRenderersMap = new Map>(); +const columnHeaderRenderersMap = new Map>(); const configEditorsMap = new Map>(); const cellConfigPanelsMap = new Map(); const editRuleValidatorsMap = new Map(); @@ -45,6 +46,8 @@ export type EditRuleValidator = ( export type ComponentType = | "cell-renderer" + | "column-header-content-renderer" + | "column-header-label-renderer" | "cell-config-panel" | "data-edit-validator"; @@ -83,6 +86,16 @@ const isCellRenderer = ( component: unknown ): component is FC => type === "cell-renderer"; +const isColumnHeaderContentRenderer = ( + type: ComponentType, + component: unknown +): component is FC => + type === "column-header-content-renderer"; +const isColumnHeaderLabelRenderer = ( + type: ComponentType, + component: unknown +): component is FC => type === "column-header-label-renderer"; + const isCellConfigPanel = ( type: ComponentType, component: unknown @@ -107,6 +120,10 @@ export function registerComponent< ): void { if (isCellRenderer(type, component)) { cellRenderersMap.set(componentName, component); + } else if (isColumnHeaderContentRenderer(type, component)) { + columnHeaderRenderersMap.set(componentName, component); + } else if (isColumnHeaderLabelRenderer(type, component)) { + columnHeaderRenderersMap.set(componentName, component); } else if (isCellConfigPanel(type, component)) { cellConfigPanelsMap.set(componentName, component); } else if (isEditRuleValidator(type, component)) { @@ -144,16 +161,17 @@ export const getRegisteredCellRenderers = ( export const getCellRendererOptions = (renderName: string) => optionsMap.get(renderName); -export function getCellRenderer( - column: ColumnDescriptor, - cellType: "cell" | "col-content" | "col-label" = "cell" -) { - if (cellType === "cell") { - return dataCellRenderer(column); - } else if (cellType === "col-label" && column.colHeaderLabelRenderer) { - return cellRenderersMap.get(column.colHeaderLabelRenderer); - } else if (cellType === "col-content" && column.colHeaderContentRenderer) { - return cellRenderersMap.get(column.colHeaderContentRenderer); +export function getCellRenderer(column: ColumnDescriptor) { + return dataCellRenderer(column); +} +export function getColumnHeaderContentRenderer(column: ColumnDescriptor) { + if (column.colHeaderContentRenderer) { + return columnHeaderRenderersMap.get(column.colHeaderContentRenderer); + } +} +export function getColumnHeaderLabelRenderer(column: ColumnDescriptor) { + if (column.colHeaderLabelRenderer) { + return columnHeaderRenderersMap.get(column.colHeaderLabelRenderer); } } diff --git a/vuu-ui/packages/vuu-utils/src/datasource-action-utils.ts b/vuu-ui/packages/vuu-utils/src/datasource-action-utils.ts new file mode 100644 index 000000000..09ac3f2ef --- /dev/null +++ b/vuu-ui/packages/vuu-utils/src/datasource-action-utils.ts @@ -0,0 +1,31 @@ +import { + DataSourceMenusMessage, + DataSourceVisualLinkCreatedMessage, + DataSourceVisualLinkRemovedMessage, + DataSourceVisualLinksMessage, + VuuFeatureMessage, +} from "@finos/vuu-data-types"; +import { GridAction } from "@finos/vuu-table-types"; + +export const isVisualLinksAction = ( + action: GridAction +): action is DataSourceVisualLinksMessage => action.type === "vuu-links"; + +export const isVisualLinkCreatedAction = ( + action: GridAction +): action is DataSourceVisualLinkCreatedMessage => + action.type === "vuu-link-created"; + +export const isVisualLinkRemovedAction = ( + action: GridAction +): action is DataSourceVisualLinkRemovedMessage => + action.type === "vuu-link-removed"; + +export const isViewportMenusAction = ( + action: GridAction +): action is DataSourceMenusMessage => action.type === "vuu-menu"; + +export const isVuuFeatureAction = ( + action: GridAction +): action is VuuFeatureMessage => + isViewportMenusAction(action) || isVisualLinksAction(action); diff --git a/vuu-ui/packages/vuu-utils/src/datasource-utils.ts b/vuu-ui/packages/vuu-utils/src/datasource-utils.ts new file mode 100644 index 000000000..5cf1f9939 --- /dev/null +++ b/vuu-ui/packages/vuu-utils/src/datasource-utils.ts @@ -0,0 +1,257 @@ +import { + ConnectionQualityMetrics, + ConnectionStatusMessage, + DataSourceConfig, + MenuRpcResponse, + RpcResponse, + TypeaheadSuggestionProvider, + VuuUIMessageIn, + VuuUIMessageInRPC, + VuuUIMessageInRPCEditReject, + VuuUIMessageInRPCEditResponse, + VuuUIMessageInTableMeta, + VuuUIMessageOutViewport, + WithFilter, + WithFullConfig, + WithGroupBy, + WithSort, +} from "@finos/vuu-data-types"; +import { + LinkDescriptorWithLabel, + VuuFilter, + VuuSort, +} from "@finos/vuu-protocol-types"; + +export const NoFilter: VuuFilter = { filter: "" }; +export const NoSort: VuuSort = { sortDefs: [] }; + +export const vanillaConfig: WithFullConfig = { + aggregations: [], + columns: [], + filter: NoFilter, + groupBy: [], + sort: NoSort, +}; + +type DataConfigPredicate = ( + config: DataSourceConfig, + newConfig: DataSourceConfig +) => boolean; + +const equivalentAggregations: DataConfigPredicate = ( + { aggregations: agg1 }, + { aggregations: agg2 } +) => + (agg1 === undefined && agg2?.length === 0) || + (agg2 === undefined && agg1?.length === 0); + +const equivalentColumns: DataConfigPredicate = ( + { columns: cols1 }, + { columns: cols2 } +) => + (cols1 === undefined && cols2?.length === 0) || + (cols2 === undefined && cols1?.length === 0); + +const equivalentFilter: DataConfigPredicate = ( + { filter: f1 }, + { filter: f2 } +) => + (f1 === undefined && f2?.filter === "") || + (f2 === undefined && f1?.filter === ""); + +const equivalentGroupBy: DataConfigPredicate = ( + { groupBy: val1 }, + { groupBy: val2 } +) => + (val1 === undefined && val2?.length === 0) || + (val2 === undefined && val1?.length === 0); + +const equivalentSort: DataConfigPredicate = ({ sort: s1 }, { sort: s2 }) => + (s1 === undefined && s2?.sortDefs.length === 0) || + (s2 === undefined && s1?.sortDefs.length === 0); + +const exactlyTheSame = (a: unknown, b: unknown) => { + if (a === b) { + return true; + } else if (a === undefined && b === undefined) { + return true; + } else { + return false; + } +}; + +const aggregationsChanged: DataConfigPredicate = (config, newConfig) => { + const { aggregations: agg1 } = config; + const { aggregations: agg2 } = newConfig; + if (exactlyTheSame(agg1, agg2) || equivalentAggregations(config, newConfig)) { + return false; + } else if (agg1 === undefined || agg2 === undefined) { + return true; + } else if (agg1.length !== agg2.length) { + return true; + } + return agg1.some( + ({ column, aggType }, i) => + column !== agg2[i].column || aggType !== agg2[i].aggType + ); +}; + +export const columnsChanged: DataConfigPredicate = (config, newConfig) => { + const { columns: cols1 } = config; + const { columns: cols2 } = newConfig; + + if (exactlyTheSame(cols1, cols2) || equivalentColumns(config, newConfig)) { + return false; + } else if (cols1 === undefined || cols2 === undefined) { + return true; + } else if (cols1?.length !== cols2?.length) { + return true; + } + return cols1.some((column, i) => column !== cols2?.[i]); +}; + +export const filterChanged: DataConfigPredicate = (c1, c2) => { + if (equivalentFilter(c1, c2)) { + return false; + } else { + return c1.filter?.filter !== c2.filter?.filter; + } +}; + +export const groupByChanged: DataConfigPredicate = (config, newConfig) => { + const { groupBy: g1 } = config; + const { groupBy: g2 } = newConfig; + if (exactlyTheSame(g1, g2) || equivalentGroupBy(config, newConfig)) { + return false; + } else if (g1 === undefined || g2 === undefined) { + return true; + } else if (g1?.length !== g2?.length) { + return true; + } + return g1.some((column, i) => column !== g2?.[i]); +}; + +const sortChanged: DataConfigPredicate = (config, newConfig) => { + const { sort: s1 } = config; + const { sort: s2 } = newConfig; + if (exactlyTheSame(s1, s2) || equivalentSort(config, newConfig)) { + return false; + } else if (s1 === undefined || s2 === undefined) { + return true; + } else if (s1?.sortDefs.length !== s2?.sortDefs.length) { + return true; + } + return s1.sortDefs.some( + ({ column, sortType }, i) => + column !== s2.sortDefs[i].column || sortType !== s2.sortDefs[i].sortType + ); +}; + +const visualLinkChanged: DataConfigPredicate = () => { + // TODO + return false; +}; + +export const configChanged = ( + config: DataSourceConfig | undefined, + newConfig: DataSourceConfig | undefined +) => { + if (exactlyTheSame(config, newConfig)) { + return false; + } + + if (config === undefined || newConfig === undefined) { + return true; + } + + return ( + aggregationsChanged(config, newConfig) || + columnsChanged(config, newConfig) || + filterChanged(config, newConfig) || + groupByChanged(config, newConfig) || + sortChanged(config, newConfig) || + visualLinkChanged(config, newConfig) + ); +}; + +export const hasGroupBy = (config?: DataSourceConfig): config is WithGroupBy => + config !== undefined && + config.groupBy !== undefined && + config.groupBy.length > 0; + +export const hasFilter = (config?: DataSourceConfig): config is WithFilter => + config?.filter !== undefined && config.filter.filter.length > 0; + +export const hasSort = (config?: DataSourceConfig): config is WithSort => + config?.sort !== undefined && + Array.isArray(config.sort?.sortDefs) && + config.sort.sortDefs.length > 0; + +export const isTypeaheadSuggestionProvider = ( + source: unknown +): source is TypeaheadSuggestionProvider => + typeof (source as TypeaheadSuggestionProvider)["getTypeaheadSuggestions"] === + "function"; + +export const isTableSchema = ( + message: VuuUIMessageIn +): message is VuuUIMessageInTableMeta => message.type === "TABLE_META_RESP"; + +export const isConnectionStatusMessage = ( + msg: object | ConnectionStatusMessage +): msg is ConnectionStatusMessage => + (msg as ConnectionStatusMessage).type === "connection-status"; + +export const isConnectionQualityMetrics = ( + msg: object +): msg is ConnectionQualityMetrics => + (msg as ConnectionQualityMetrics).type === "connection-metrics"; + +export const messageHasResult = (msg: object): msg is VuuUIMessageInRPC => + typeof (msg as VuuUIMessageInRPC).result !== "undefined"; + +export const isErrorResponse = ( + response?: RpcResponse +): response is VuuUIMessageInRPCEditReject => + response !== undefined && "error" in response; + +export const hasAction = ( + response?: RpcResponse +): response is MenuRpcResponse | VuuUIMessageInRPCEditResponse => + response != undefined && "action" in response; + +export const isViewporttMessage = ( + msg: object +): msg is VuuUIMessageOutViewport => "viewport" in msg; + +export const withConfigDefaults = ( + config: DataSourceConfig +): WithFullConfig & { visualLink?: LinkDescriptorWithLabel } => { + if ( + config.aggregations && + config.columns && + config.filter && + config.groupBy && + config.sort + ) { + return config as WithFullConfig; + } else { + const { + aggregations = [], + columns = [], + filter = { filter: "" }, + groupBy = [], + sort = { sortDefs: [] }, + visualLink, + } = config; + + return { + aggregations, + columns, + filter, + groupBy, + sort, + visualLink, + }; + } +}; diff --git a/vuu-ui/packages/vuu-utils/src/date/formatter.ts b/vuu-ui/packages/vuu-utils/src/date/formatter.ts index 7228f1359..f661ab850 100644 --- a/vuu-ui/packages/vuu-utils/src/date/formatter.ts +++ b/vuu-ui/packages/vuu-utils/src/date/formatter.ts @@ -1,9 +1,9 @@ +import { isNotNullOrUndefined } from "../ts-utils"; import { DatePattern, DateTimePattern, TimePattern } from "./types"; type DateTimeFormatConfig = { locale?: string; options: Intl.DateTimeFormatOptions; - postProcessor?: (s: string) => string; }; // Time format config @@ -31,9 +31,8 @@ const baseDateFormatOptions: Intl.DateTimeFormatOptions = { }; const formatConfigByDatePatterns: Record = { "dd.mm.yyyy": { - locale: "en-GB", + locale: "de-De", options: { ...baseDateFormatOptions }, - postProcessor: (s) => s.replaceAll("/", "."), }, "dd/mm/yyyy": { locale: "en-GB", options: { ...baseDateFormatOptions } }, "dd MMM yyyy": { @@ -55,19 +54,17 @@ const formatConfigByDatePatterns: Record = { }, }; -const formatConfigByDateTimePatterns: Record< - DateTimePattern, - DateTimeFormatConfig -> = { ...formatConfigByDatePatterns, ...formatConfigByTimePatterns }; +function getFormatConfigs(pattern: DateTimePattern) { + return [ + pattern.date ? formatConfigByDatePatterns[pattern.date] : null, + pattern.time ? formatConfigByTimePatterns[pattern.time] : null, + ]; +} export function formatDate(pattern: DateTimePattern): (d: Date) => string { - const { locale, options, postProcessor } = - formatConfigByDateTimePatterns[pattern]; - const dateTimeFormat = Intl.DateTimeFormat(locale, options); + const dateTimeFormats = getFormatConfigs(pattern) + .filter(isNotNullOrUndefined) + .map((c) => Intl.DateTimeFormat(c.locale, c.options)); - return (d) => { - const dateStr = dateTimeFormat.format(d); - console.log({ dateStr }); - return postProcessor ? postProcessor(dateStr) : dateStr; - }; + return (d) => dateTimeFormats.map((dtf) => dtf.format(d)).join(" "); } diff --git a/vuu-ui/packages/vuu-utils/src/date/helpers.ts b/vuu-ui/packages/vuu-utils/src/date/helpers.ts index f78eeae28..23a735d13 100644 --- a/vuu-ui/packages/vuu-utils/src/date/helpers.ts +++ b/vuu-ui/packages/vuu-utils/src/date/helpers.ts @@ -1,11 +1,15 @@ -import { DateTimeColumnTypeSimple } from "@finos/vuu-table-types"; -import { DateTimeColumnDescriptor, isTypeDescriptor } from "../column-utils"; +import { DateTimeColumnDescriptor } from "@finos/vuu-table-types"; +import { isTypeDescriptor } from "../column-utils"; import { DateTimePattern, isDateTimePattern } from "./types"; -export const defaultPatternByTypes: Record< - DateTimeColumnTypeSimple, - DateTimePattern -> = { time: "hh:mm:ss", date: "dd.mm.yyyy" }; +export const defaultPatternsByType = { + time: "hh:mm:ss", + date: "dd.mm.yyyy", +} as const; + +export const fallbackDateTimePattern: DateTimePattern = { + date: defaultPatternsByType["date"], +}; export function dateTimePattern( type: DateTimeColumnDescriptor["type"] @@ -14,9 +18,7 @@ export function dateTimePattern( if (type.formatting && isDateTimePattern(type.formatting.pattern)) { return type.formatting.pattern; } - - return defaultPatternByTypes[type.name]; - } else { - return defaultPatternByTypes[type]; } + + return fallbackDateTimePattern; } diff --git a/vuu-ui/packages/vuu-utils/src/date/index.ts b/vuu-ui/packages/vuu-utils/src/date/index.ts index a7c31af09..a6d6412df 100644 --- a/vuu-ui/packages/vuu-utils/src/date/index.ts +++ b/vuu-ui/packages/vuu-utils/src/date/index.ts @@ -1,2 +1,7 @@ export * from "./formatter"; -export { isDateTimePattern, type DateTimePattern } from "./types"; +export { + isDateTimePattern, + type DateTimePattern, + supportedDateTimePatterns, +} from "./types"; +export { defaultPatternsByType, fallbackDateTimePattern } from "./helpers"; diff --git a/vuu-ui/packages/vuu-utils/src/date/types.ts b/vuu-ui/packages/vuu-utils/src/date/types.ts index 71727a8c4..f5ae5f6dc 100644 --- a/vuu-ui/packages/vuu-utils/src/date/types.ts +++ b/vuu-ui/packages/vuu-utils/src/date/types.ts @@ -1,3 +1,5 @@ +import { ColumnTypeFormatting } from "@finos/vuu-table-types"; + const supportedDatePatterns = [ "dd.mm.yyyy", "dd/mm/yyyy", @@ -10,17 +12,25 @@ const supportedDatePatterns = [ const supportedTimePatterns = ["hh:mm:ss", "hh:mm:ss a"] as const; +export const supportedDateTimePatterns = { + date: supportedDatePatterns, + time: supportedTimePatterns, +}; + export type DatePattern = (typeof supportedDatePatterns)[number]; export type TimePattern = (typeof supportedTimePatterns)[number]; -export type DateTimePattern = DatePattern | TimePattern; -const isDatePattern = (pattern: string): pattern is DatePattern => +export type DateTimePattern = + | { date?: DatePattern; time: TimePattern } + | { date: DatePattern; time?: TimePattern }; + +const isDatePattern = (pattern?: string): pattern is DatePattern => supportedDatePatterns.includes(pattern as DatePattern); -const isTimePattern = (pattern: string): pattern is TimePattern => +const isTimePattern = (pattern?: string): pattern is TimePattern => supportedTimePatterns.includes(pattern as TimePattern); export const isDateTimePattern = ( - pattern?: string + pattern?: ColumnTypeFormatting["pattern"] ): pattern is DateTimePattern => - pattern !== undefined && (isDatePattern(pattern) || isTimePattern(pattern)); + isDatePattern(pattern?.date) || isTimePattern(pattern?.time); diff --git a/vuu-ui/packages/vuu-utils/src/event-emitter.ts b/vuu-ui/packages/vuu-utils/src/event-emitter.ts index 1cd4b6b3c..7b3a5176e 100644 --- a/vuu-ui/packages/vuu-utils/src/event-emitter.ts +++ b/vuu-ui/packages/vuu-utils/src/event-emitter.ts @@ -13,7 +13,17 @@ function isOnlyListener( return !Array.isArray(listeners); } -export class EventEmitter { +export interface IEventEmitter { + addListener(event: E, listener: Events[E]): void; + emit(event: E, ...args: Parameters): void; + on(event: E, listener: Events[E]): void; + removeListener(event: E, listener: Events[E]): void; + removeAllListeners(event?: E): void; +} + +export class EventEmitter + implements IEventEmitter +{ #events: Map = new Map(); addListener(event: E, listener: Events[E]) { diff --git a/vuu-ui/packages/vuu-utils/src/formatting-utils.ts b/vuu-ui/packages/vuu-utils/src/formatting-utils.ts index 7d9e5aeac..eaa3f4d91 100644 --- a/vuu-ui/packages/vuu-utils/src/formatting-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/formatting-utils.ts @@ -2,13 +2,13 @@ import { ColumnDescriptor, ColumnTypeValueMap, ColumnTypeFormatting, + DateTimeColumnDescriptor, } from "@finos/vuu-table-types"; import { roundDecimal } from "./round-decimal"; import { isDateTimeColumn, isTypeDescriptor, isMappedValueTypeRenderer, - DateTimeColumnDescriptor, } from "./column-utils"; import { formatDate } from "./date"; import { dateTimePattern } from "./date/helpers"; diff --git a/vuu-ui/packages/vuu-utils/src/index.ts b/vuu-ui/packages/vuu-utils/src/index.ts index bd8193117..217485db8 100644 --- a/vuu-ui/packages/vuu-utils/src/index.ts +++ b/vuu-ui/packages/vuu-utils/src/index.ts @@ -6,6 +6,8 @@ export * from "./component-registry"; export * from "./DataWindow"; export * from "./common-types"; export * from "./data-utils"; +export * from "./datasource-action-utils"; +export * from "./datasource-utils"; export * from "./date"; export * from "./debug-utils"; export * from "./filter-utils"; @@ -30,5 +32,8 @@ export * from "./row-utils"; export * from "./selection-utils"; export * from "./sort-utils"; export * from "./text-utils"; +export * from "./ThemeProvider"; +export * from "./ts-utils"; export * from "./url-utils"; -export * from "./screenshot-utils"; +export * from "./useId"; +export * from "./useLayoutEffectSkipFirst"; diff --git a/vuu-ui/packages/vuu-utils/src/invariant.ts b/vuu-ui/packages/vuu-utils/src/invariant.ts index 7ead61252..9472bd841 100644 --- a/vuu-ui/packages/vuu-utils/src/invariant.ts +++ b/vuu-ui/packages/vuu-utils/src/invariant.ts @@ -1,8 +1,9 @@ export function invariant(condition: boolean, message: string) { if (!condition) { const error = new Error(message); - error.name = 'Invariant Violation'; + error.name = "Invariant Violation"; // TODO what is framesToPop? + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore error.framesToPop = 1; // we don't care about invariant's own frame throw error; diff --git a/vuu-ui/packages/vuu-utils/src/nanoid/index.ts b/vuu-ui/packages/vuu-utils/src/nanoid/index.ts index ecee1daa5..1149dd377 100644 --- a/vuu-ui/packages/vuu-utils/src/nanoid/index.ts +++ b/vuu-ui/packages/vuu-utils/src/nanoid/index.ts @@ -2,9 +2,9 @@ // couldn't get original code to work as npm import without crypro warnings - // seemed to be picking up node version, not browser version -export const uuid = (size: number = 21): string => { - let id: string = ''; - let bytes = crypto.getRandomValues(new Uint8Array(size)); +export const uuid = (size = 21): string => { + let id = ''; + const bytes = crypto.getRandomValues(new Uint8Array(size)); // A compact alternative for `for (var i = 0; i < step; i++)`. while (size--) { @@ -13,7 +13,7 @@ export const uuid = (size: number = 21): string => { // range to the 0-63 value range. Therefore, adding hacks, such // as empty string fallback or magic numbers, is unneccessary because // the bitmask trims bytes down to the alphabet size. - let byte = bytes[size] & 63; + const byte = bytes[size] & 63; if (byte < 36) { // `0-9a-z` id += byte.toString(36); diff --git a/vuu-ui/packages/vuu-utils/src/row-utils.ts b/vuu-ui/packages/vuu-utils/src/row-utils.ts index e2762e073..74079eb97 100644 --- a/vuu-ui/packages/vuu-utils/src/row-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/row-utils.ts @@ -1,6 +1,6 @@ import { DataSourceRow } from "@finos/vuu-data-types"; -import { metadataKeys } from "@finos/vuu-utils"; import { MutableRefObject } from "react"; +import { metadataKeys } from "./column-utils"; const { IDX } = metadataKeys; diff --git a/vuu-ui/packages/vuu-utils/src/screenshot-utils.ts b/vuu-ui/packages/vuu-utils/src/screenshot-utils.ts deleted file mode 100644 index 1cee30205..000000000 --- a/vuu-ui/packages/vuu-utils/src/screenshot-utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { toPng } from "html-to-image"; - -/** - * Takes a screenshot of the given node and returns the base64 encoded image url - * @param node Node to take screenshot of - * @returns Base64 encoded image url - */ -export async function takeScreenshot(node: HTMLElement) { - - const screenshot = await toPng(node, { cacheBust: true }) - .then((dataUrl) => { - return dataUrl; - }) - .catch((err) => { - console.error("Error taking screenshot", err); - return undefined; - }); - - if (!screenshot) { - return undefined; - } - return screenshot; -} diff --git a/vuu-ui/packages/vuu-utils/src/selection-utils.ts b/vuu-ui/packages/vuu-utils/src/selection-utils.ts index 71c433546..7f0a70eb8 100644 --- a/vuu-ui/packages/vuu-utils/src/selection-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/selection-utils.ts @@ -1,10 +1,10 @@ -import { DataSourceRow } from "@finos/vuu-data-types"; import { + DataSourceRow, RangeTuple, Selection, SelectionItem, - TableSelectionModel, -} from "@finos/vuu-table-types"; +} from "@finos/vuu-data-types"; +import { TableSelectionModel } from "@finos/vuu-table-types"; import { metadataKeys } from "./column-utils"; const NO_SELECTION: number[] = []; diff --git a/vuu-ui/packages/vuu-utils/src/ts-utils.ts b/vuu-ui/packages/vuu-utils/src/ts-utils.ts new file mode 100644 index 000000000..dcbb12e4c --- /dev/null +++ b/vuu-ui/packages/vuu-utils/src/ts-utils.ts @@ -0,0 +1,5 @@ +export function isNotNullOrUndefined( + value: T | undefined | null +): value is NonNullable { + return value !== undefined && value !== null; +} diff --git a/vuu-ui/packages/vuu-utils/src/useId.ts b/vuu-ui/packages/vuu-utils/src/useId.ts new file mode 100644 index 000000000..e930329aa --- /dev/null +++ b/vuu-ui/packages/vuu-utils/src/useId.ts @@ -0,0 +1,6 @@ +import { useMemo } from "react"; + +let vuuComponentIdCount = 0; + +export const useId = (id?: string) => + useMemo(() => id ?? `vuu-${++vuuComponentIdCount}`, [id]); diff --git a/vuu-ui/packages/vuu-utils/src/useLayoutEffectSkipFirst.ts b/vuu-ui/packages/vuu-utils/src/useLayoutEffectSkipFirst.ts new file mode 100644 index 000000000..eb7284f8b --- /dev/null +++ b/vuu-ui/packages/vuu-utils/src/useLayoutEffectSkipFirst.ts @@ -0,0 +1,16 @@ +import { DependencyList, EffectCallback, useLayoutEffect, useRef } from "react"; + +export const useLayoutEffectSkipFirst = ( + func: EffectCallback, + deps: DependencyList +) => { + const goodToGo = useRef(false); + useLayoutEffect(() => { + if (goodToGo.current) { + func(); + } else { + goodToGo.current = true; + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps); +}; diff --git a/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts b/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts index 68df33b8a..95da9f534 100644 --- a/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts +++ b/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts @@ -6,15 +6,23 @@ const testDate = new Date(2010, 5, 12, 15, 50, 37); describe("formatDate", () => { it.each<{ pattern: DateTimePattern; expected: string }>([ - { pattern: "dd.mm.yyyy", expected: "12.06.2010" }, - { pattern: "dd/mm/yyyy", expected: "12/06/2010" }, - { pattern: "dd MMM yyyy", expected: "12 Jun 2010" }, - { pattern: "dd MMMM yyyy", expected: "12 June 2010" }, - { pattern: "mm/dd/yyyy", expected: "06/12/2010" }, - { pattern: "MMM dd, yyyy", expected: "Jun 12, 2010" }, - { pattern: "MMMM dd, yyyy", expected: "June 12, 2010" }, - { pattern: "hh:mm:ss", expected: "15:50:37" }, - { pattern: "hh:mm:ss a", expected: "03:50:37 pm" }, + { pattern: { date: "dd.mm.yyyy" }, expected: "12.06.2010" }, + { pattern: { date: "dd/mm/yyyy" }, expected: "12/06/2010" }, + { pattern: { date: "dd MMM yyyy" }, expected: "12 Jun 2010" }, + { pattern: { date: "dd MMMM yyyy" }, expected: "12 June 2010" }, + { pattern: { date: "mm/dd/yyyy" }, expected: "06/12/2010" }, + { pattern: { date: "MMM dd, yyyy" }, expected: "Jun 12, 2010" }, + { pattern: { date: "MMMM dd, yyyy" }, expected: "June 12, 2010" }, + { pattern: { time: "hh:mm:ss" }, expected: "15:50:37" }, + { pattern: { time: "hh:mm:ss a" }, expected: "03:50:37 pm" }, + { + pattern: { date: "dd.mm.yyyy", time: "hh:mm:ss a" }, + expected: "12.06.2010 03:50:37 pm", + }, + { + pattern: { date: "MMMM dd, yyyy", time: "hh:mm:ss a" }, + expected: "June 12, 2010 03:50:37 pm", + }, ])( "can correctly format date with the given pattern $pattern", ({ pattern, expected }) => { diff --git a/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts b/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts index ab6974055..8a34cf6d4 100644 --- a/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts +++ b/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts @@ -1,28 +1,31 @@ import { describe, expect, it } from "vitest"; -import { dateTimePattern, defaultPatternByTypes } from "../../src/date/helpers"; +import { + dateTimePattern, + fallbackDateTimePattern, +} from "../../src/date/helpers"; import { DateTimePattern } from "../../src/date/types"; -const testPattern: DateTimePattern = "mm/dd/yyyy"; +const testPattern: DateTimePattern = { date: "mm/dd/yyyy" }; describe("dateTimePattern", () => { it("returns exact pattern when found in descriptor type", () => { const type = { - name: "date" as const, + name: "date/time" as const, formatting: { pattern: testPattern }, }; const actualPattern = dateTimePattern(type); expect(actualPattern).toEqual(testPattern); }); - it("falls back to default when pattern not found in descriptor type", () => { - const type = { name: "time" as const, formatting: {} }; + it("fallback pattern when pattern not found in descriptor type", () => { + const type = { name: "date/time" as const, formatting: {} }; const actualPattern = dateTimePattern(type); - expect(actualPattern).toEqual(defaultPatternByTypes["time"]); + expect(actualPattern).toEqual(fallbackDateTimePattern); }); - it("falls back to default when simple type", () => { - const type = "date"; + it("fallback pattern when simple type", () => { + const type = "date/time"; const actualPattern = dateTimePattern(type); - expect(actualPattern).toEqual(defaultPatternByTypes["date"]); + expect(actualPattern).toEqual(fallbackDateTimePattern); }); }); diff --git a/vuu-ui/packages/vuu-utils/test/date/types.test.ts b/vuu-ui/packages/vuu-utils/test/date/types.test.ts index 3f35da7d5..33e094f9a 100644 --- a/vuu-ui/packages/vuu-utils/test/date/types.test.ts +++ b/vuu-ui/packages/vuu-utils/test/date/types.test.ts @@ -1,13 +1,15 @@ import { describe, expect, it } from "vitest"; import { isDateTimePattern } from "../../src/date/types"; +import { ColumnTypeFormatting } from "@finos/vuu-table-types"; describe("isDateTimePattern", () => { - it.each<{ pattern: string | undefined; expected: boolean }>([ - { pattern: "dd MMM yyyy", expected: true }, - { pattern: "not-a-date-time-pattern", expected: false }, + it.each<{ pattern: ColumnTypeFormatting["pattern"]; expected: boolean }>([ + { pattern: { date: "dd MMM yyyy" }, expected: true }, + { pattern: { time: "hh:mm:ss a" }, expected: true }, + { pattern: { date: "dd/mm/yyyy", time: "hh:mm:ss" }, expected: true }, { pattern: undefined, expected: false }, ])( - "returns $expected when pattern is a DateTimePattern", + "returns true only when pattern is a DateTimePattern", ({ pattern, expected }) => { const actual = isDateTimePattern(pattern); expect(actual).toEqual(expected); diff --git a/vuu-ui/packages/vuu-utils/test/row-utils.test.ts b/vuu-ui/packages/vuu-utils/test/row-utils.test.ts index 848bae578..01c1a536c 100644 --- a/vuu-ui/packages/vuu-utils/test/row-utils.test.ts +++ b/vuu-ui/packages/vuu-utils/test/row-utils.test.ts @@ -1,4 +1,4 @@ -import { DataSourceRow } from "@finos/vuu-data"; +import { DataSourceRow } from "@finos/vuu-data-types"; import { describe, expect, it } from "vitest"; import { actualRowPositioning, virtualRowPositioning } from "../src/row-utils"; diff --git a/vuu-ui/packages/vuu-utils/test/utils.ts b/vuu-ui/packages/vuu-utils/test/utils.ts new file mode 100644 index 000000000..1dff87194 --- /dev/null +++ b/vuu-ui/packages/vuu-utils/test/utils.ts @@ -0,0 +1,8 @@ +import { expect } from "vitest"; + +export const expectPromiseRejectsWithError = ( + f: () => Promise, + message: string +) => { + expect(f).rejects.toStrictEqual(new Error(message)); +}; diff --git a/vuu-ui/sample-apps/app-vuu-example/demo.tsx b/vuu-ui/sample-apps/app-vuu-example/demo.tsx index f82aa7fc9..00bbff9cc 100644 --- a/vuu-ui/sample-apps/app-vuu-example/demo.tsx +++ b/vuu-ui/sample-apps/app-vuu-example/demo.tsx @@ -1,7 +1,7 @@ +import { LoginPanel } from "@finos/vuu-shell"; +import { ThemeProvider, uuid } from "@finos/vuu-utils"; import React from "react"; import ReactDOM from "react-dom"; -import { LoginPanel, ThemeProvider } from "@finos/vuu-shell"; -import { uuid } from "@finos/vuu-utils"; import "@finos/vuu-icons/index.css"; import "@finos/vuu-theme/index.css"; diff --git a/vuu-ui/sample-apps/app-vuu-example/login.tsx b/vuu-ui/sample-apps/app-vuu-example/login.tsx index 925da5457..e208f0a97 100644 --- a/vuu-ui/sample-apps/app-vuu-example/login.tsx +++ b/vuu-ui/sample-apps/app-vuu-example/login.tsx @@ -1,11 +1,11 @@ +import { authenticate } from "@finos/vuu-data-remote"; +import { LoginPanel } from "@finos/vuu-shell"; +import { ThemeProvider } from "@finos/vuu-utils"; import React from "react"; import ReactDOM from "react-dom"; -import { LoginPanel, ThemeProvider } from "@finos/vuu-shell"; -import { authenticate } from "@finos/vuu-data"; import "@finos/vuu-icons/index.css"; import "@finos/vuu-theme/index.css"; - import "./login.css"; async function login(username: string, password = "password") { diff --git a/vuu-ui/sample-apps/app-vuu-example/package.json b/vuu-ui/sample-apps/app-vuu-example/package.json index c95685008..a0781411f 100644 --- a/vuu-ui/sample-apps/app-vuu-example/package.json +++ b/vuu-ui/sample-apps/app-vuu-example/package.json @@ -17,7 +17,7 @@ "devDependencies": {}, "dependencies": { "@fontsource/open-sans": "^4.5.13", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15", "@finos/vuu-data": "0.0.26", "@finos/vuu-table-types": "0.0.26", @@ -26,9 +26,9 @@ "@finos/vuu-popups": "0.0.26", "@finos/vuu-shell": "0.0.26", "@finos/vuu-utils": "0.0.26", - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" }, "engines": { "node": ">=16.0.0" diff --git a/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts b/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts index 888487e2a..881d66b9a 100644 --- a/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts +++ b/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts @@ -132,7 +132,7 @@ const columnMetaData: { [key: string]: Partial } = { label: "Created", name: "created", type: { - name: "time", + name: "date/time", }, }, currency: { @@ -196,7 +196,7 @@ const columnMetaData: { [key: string]: Partial } = { label: "Last Update", name: "lastUpdate", type: { - name: "time", + name: "date/time", }, }, lotSize: { diff --git a/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts b/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts index 91dc3cb01..3d036a6e3 100644 --- a/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts +++ b/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts @@ -2,7 +2,7 @@ import { MenuRpcResponse, OpenDialogAction, TableSchema, -} from "@finos/vuu-data"; +} from "@finos/vuu-data-types"; import { FormConfig, FormFieldDescriptor } from "@finos/vuu-shell"; const static_config: { [key: string]: Partial } = { diff --git a/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts b/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts index 81fe3da34..43f4f04ef 100644 --- a/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts +++ b/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts @@ -1,4 +1,5 @@ import { useVuuTables } from "@finos/vuu-data-react"; +import { TableSchema } from "@finos/vuu-data-types"; import { FeatureProps, Features, @@ -6,7 +7,6 @@ import { isWildcardSchema, } from "@finos/vuu-shell"; import { wordify } from "@finos/vuu-utils"; -import { TableSchema } from "@finos/vuu-data"; import { useMemo } from "react"; export interface FeaturesHookProps { @@ -27,7 +27,7 @@ export const useFeatures = ({ leftNavLocation = "vuu-tables", ...feature } of Object.values(featuresProp)) { - const { schema, schemas } = featureProps; + const { schema, schemas, ViewProps } = featureProps; const target = leftNavLocation === "vuu-tables" ? tableFeatures : features; if (isWildcardSchema(schema) && tables) { @@ -50,6 +50,7 @@ export const useFeatures = ({ ComponentProps: { tableSchema, }, + ViewProps, }); } else if (Array.isArray(schemas)) { target.push({ @@ -63,6 +64,7 @@ export const useFeatures = ({ }, {} ), + ViewProps, }); } else { target.push(feature); diff --git a/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx b/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx index 15b6292b0..11b147d7f 100644 --- a/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx +++ b/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx @@ -1,10 +1,11 @@ import { RpcResponseHandler, useVuuTables } from "@finos/vuu-data-react"; -import { hasAction, MenuRpcResponse, TableSchema } from "@finos/vuu-data"; +import { MenuRpcResponse, TableSchema } from "@finos/vuu-data-types"; +import { SetDialog } from "@finos/vuu-popups"; +import { VuuTable } from "@finos/vuu-protocol-types"; +import { Feature, SessionEditingForm } from "@finos/vuu-shell"; +import { hasAction } from "@finos/vuu-utils"; import { useCallback } from "react"; import { getFormConfig } from "./session-editing"; -import { Feature, SessionEditingForm } from "@finos/vuu-shell"; -import { VuuTable } from "@finos/vuu-protocol-types"; -import { SetDialog } from "@finos/vuu-popups"; const withTable = (action: unknown): action is { table: VuuTable } => action !== null && typeof action === "object" && "table" in action; diff --git a/vuu-ui/sample-apps/feature-basket-trading/package.json b/vuu-ui/sample-apps/feature-basket-trading/package.json index 74fefb227..23f691808 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/package.json +++ b/vuu-ui/sample-apps/feature-basket-trading/package.json @@ -14,28 +14,30 @@ "sideEffects": [ "**/*.css" ], - "devDependencies": {}, + "devDependencies": { + "@finos/vuu-data-types": "0.0.26", + "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" + }, "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-table-types": "0.0.26", "@finos/vuu-filters": "0.0.26", - "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26", "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" }, "engines": { "node": ">=16.0.0" diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx index ae371c12a..3e60d8efc 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx @@ -1,4 +1,4 @@ -import { TableSchema } from "@finos/vuu-data"; +import { TableSchema } from "@finos/vuu-data-types"; import { FlexboxLayout, Stack } from "@finos/vuu-layout"; import { BasketTableEdit } from "./basket-table-edit"; import { BasketTableLive } from "./basket-table-live"; @@ -35,8 +35,12 @@ const VuuBasketTradingFeature = (props: BasketTradingFeatureProps) => { basketSelectorProps, dataSourceBasketTradingConstituentJoin, dialog, + editConfig, + liveConfig, onClickAddBasket, onCommitBasketChange, + onConfigChangeEdit, + onConfigChangeLive, onDropInstrument, onSendToMarket, onTakeOffMarket, @@ -78,19 +82,22 @@ const VuuBasketTradingFeature = (props: BasketTradingFeatureProps) => { diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css index 7b309f74e..5922af5da 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css @@ -1,10 +1,8 @@ .vuuBasketSelector { - --basket-selector-height: var(--vuuBasketSelector-height, 61px); + --basket-selector-height: 61px; align-items: center; border: solid 1px var(--vuu-color-gray-45); border-radius: 6px; - container-name: basket-selector; - container-type: size; display: inline-block; height: var(--basket-selector-height); min-width: 450px; @@ -101,14 +99,3 @@ flex: 0 0 36px; justify-content: center; } - -@container basket-selector (height < 59px) { - .vuuBasketSelector-basketDetails { - grid-template-columns: max-content min-content min-content 1fr; - grid-template-rows: 1fr; - padding: 4px 8px; - } - label { - display: none; - } -} \ No newline at end of file diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx index 7b23b2d50..8b1414b3b 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx @@ -1,13 +1,17 @@ -import { DropdownBase, PriceTicker } from "@finos/vuu-ui-controls"; +import { DataSource } from "@finos/vuu-data-types"; +import { + DropdownBase, + DropdownBaseProps, + InstrumentSearch, + PriceTicker, +} from "@finos/vuu-ui-controls"; +import { useId } from "@finos/vuu-utils"; import { Button } from "@salt-ds/core"; -import { DataSource } from "@finos/vuu-data"; -import { useId } from "@finos/vuu-layout"; -import { DropdownBaseProps, InstrumentSearch } from "@finos/vuu-ui-controls"; import { HTMLAttributes, useRef } from "react"; +import { Basket } from "../useBasketTrading"; import "./BasketSelector.css"; import { useBasketSelector } from "./useBasketSelector"; -import { Basket } from "../useBasketTrading"; const classBase = "vuuBasketSelector"; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx index 706d7ed0e..fa2cdf6cc 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx @@ -1,4 +1,4 @@ -import cx from "classnames"; +import cx from "clsx"; import { RowProps } from "@finos/vuu-table"; import { MouseEvent, useCallback } from "react"; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx index 0202d08bc..1c424cb57 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx @@ -1,12 +1,8 @@ -import { TableSchema } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-table-types"; import { Table, TableProps } from "@finos/vuu-table"; import { ContextMenuConfiguration, ContextMenuProvider, } from "@finos/vuu-popups"; -import { useMemo } from "react"; -import columns from "./basketConstituentEditColumns"; import { ColHeaderAddSymbol } from "../cell-renderers"; import "./BasketTableEdit.css"; @@ -17,35 +13,22 @@ if (typeof ColHeaderAddSymbol !== "function") { console.warn("BasketTableEdit not all custom cell renderers are available"); } -export interface BasketTableEditProps extends Omit { +export interface BasketTableEditProps extends TableProps { contextMenuConfig: ContextMenuConfiguration; - tableSchema: TableSchema; } export const BasketTableEdit = ({ contextMenuConfig, - dataSource, - tableSchema, ...props }: BasketTableEditProps) => { - const tableConfig = useMemo( - () => ({ - columns, - rowSeparators: true, - }), - [] - ); - return ( diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts index 21f5319c3..6dbaa8f37 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "packages/vuu-table-types"; +import type { ColumnDescriptor } from "@finos/vuu-table-types"; const editable = true; const hidden = true; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx index e4f40c1c3..eeb1b3635 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx @@ -1,9 +1,5 @@ -import { TableSchema } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-table-types"; import { Table, TableProps } from "@finos/vuu-table"; -import { useMemo } from "react"; import { ProgressCell, SpreadCell, StatusCell } from "../cell-renderers"; -import columns from "./basketConstituentLiveColumns"; if ( typeof ProgressCell !== "function" || @@ -17,28 +13,12 @@ import "./BasketTableLive.css"; const classBase = "vuuBasketTableLive"; -export interface BasketTableLiveProps extends Omit { - tableSchema: TableSchema; -} - -export const BasketTableLive = ({ - tableSchema, - ...props -}: BasketTableLiveProps) => { - const tableConfig = useMemo( - () => ({ - columns, - rowSeparators: true, - }), - [] - ); - +export const BasketTableLive = ({ ...props }: TableProps) => { return (
); diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts index 8041aba72..76048e1a1 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "packages/vuu-table-types"; +import type { ColumnDescriptor } from "@finos/vuu-table-types"; const hidden = true; const ticking = { diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx index a63ff956f..e229aa8c9 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx @@ -5,7 +5,7 @@ import { MenuBuilder, } from "@finos/vuu-data-types"; import { useMemo } from "react"; -import cx from "classnames"; +import cx from "clsx"; import "./BasketMenu.css"; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css index a42da233b..db94ffbf3 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css @@ -15,7 +15,9 @@ --saltFormField-width: fit-content; - flex: 0 0 var(--basket-toolbar-height, 75px); + border-bottom: solid 1px var(--vuu-color-gray-05); + flex: 0 0 var(--basket-toolbar-height, 110px); + margin-bottom: 8px; padding: 8px 16px; } @@ -36,10 +38,10 @@ column-gap: 24px; row-gap: 0px; grid-template-columns: auto auto auto auto auto 1fr; - grid-template-rows: 18px 18px 18px 18px; + grid-template-rows: 15px 15px 15px 16px 32px; } -.vuuBasketToolbar-on-market .vuuBasketToolbar-inner { +.vuuBasketToolbar-on-market { --basket-status-gridColumn: 2; --basket-status-gridRow: 1/5; --basket-side-gridColumn: 3; @@ -185,234 +187,22 @@ white-space: nowrap; } - @container basket-toolbar (width < 1200px) { .vuuBasketToolbar-inner { - grid-template-columns: auto auto auto 1fr; - } - - .saltFormField-labelTop { - align-self: center; - grid-template-areas: "label content"; - } - .vuuBasketToolbar-inner { - --basket-side-gridColumn: 2; - --basket-side-gridRow: 1/3; - --basket-units-gridColumn: 2; - --basket-units-gridRow: 3/5; - --basket-notionalUsd-gridColumn: 3; - --basket-notionalUsd-gridRow: 1/3; - --basket-notional-gridColumn: 3; - --basket-notional-gridRow: 3/5; - --basket-sendtomarket-gridColumn: 4; - } - - .vuuBasketToolbar-sideField { - align-self: end; - } - - .vuuBasketToolbar-sideField .saltFormFieldLabel, - .vuuBasketToolbar-unitsField .saltFormFieldLabel { - align-self: center; - width: 28px; - } - - .vuuBasketToolbar-side { - --saltButton-height: 24px; - } - .vuuBasketToolbar-units { - --vuuExpandoInput-height: 24px; - } - - .vuuBasketToolbar-notionalUsdField { - align-self: end; - } - - .vuuBasketToolbar-notionalField { - margin: 0; - } - - .vuuBasketToolbar-notionalUsdField .saltFormFieldLabel, - .vuuBasketToolbar-notionalField .saltFormFieldLabel { - align-self: center; - - width: 70px; - } - - .vuuBasketToolbar-notionalField:before { - content: none; - } - -} - - -@container basket-toolbar (width < 1080px) { - .vuuBasketToolbar-inner { - --vuuBasketSelector-height: 36px; - grid-template-columns: auto auto auto; - } - - .saltFormField-labelTop { - grid-template-areas: "label content"; - } - .vuuBasketToolbar-inner { - --basket-selector-gridRow: 1/3; - --basket-side-gridColumn: 2; - --basket-side-gridRow: 1/3; - --basket-units-gridColumn: 2; - --basket-units-gridRow: 3/5; - --basket-notionalUsd-gridColumn: 3; - --basket-notionalUsd-gridRow: 1/3; - --basket-notional-gridColumn: 3; - --basket-notional-gridRow: 3/5; --basket-sendtomarket-gridColumn: 1; - --basket-sendtomarket-gridRow: 3/5; - } - - .vuuBasketToolbar-sideField { - align-self: end; - } - - .vuuBasketToolbar-sideField .saltFormFieldLabel, - .vuuBasketToolbar-unitsField .saltFormFieldLabel { - width: 28px; - } - - .vuuBasketToolbar-side { - --saltButton-height: 24px; - } - .vuuBasketToolbar-units { - --vuuExpandoInput-height: 24px; - } - - .vuuBasketToolbar-notionalUsdField { - align-self: end; - } - - .vuuBasketToolbar-notionalField { - margin: 0; - } - - .vuuBasketToolbar-notionalUsdField .saltFormFieldLabel, - .vuuBasketToolbar-notionalField .saltFormFieldLabel { - width: 70px; - } - - .vuuBasketToolbar-notionalField:before { - content: none; - } + --basket-sendtomarket-gridRow: 5/6; - .vuuBasketToolbar-sendToMarket { - justify-self: end; + grid-template-columns: auto auto auto auto 1fr; } - -} - -@container basket-toolbar-live (width < 1660px) { - - .vuuBasketToolbar-on-market .vuuBasketToolbar-inner { - --basket-actions-gridColumn: 8; - --basket-actions-gridRow: 1/3; - --basket-takeoffmarket-gridColumn: 8; - --basket-takeoffmarket-gridRow: 3/5; - - grid-template-columns: auto auto auto auto auto 1fr; - } - - .vuuBasketToolbar-actions { - align-self: end;; - } - } - -@container basket-toolbar-live (width < 1500px) { - - .vuuBasketToolbar-on-market .vuuBasketToolbar-inner { - - --basket-side-gridColumn: 3; - --basket-side-gridRow: 1/3; - --basket-units-gridColumn: 3; - --basket-units-gridRow: 3/5; - --basket-notionalUsd-gridColumn: 4; - --basket-notionalUsd-gridRow: 1/5; - --basket-notional-gridColumn: 5; - --basket-notional-gridRow: 1/5; - --basket-pctfilled-gridColumn: 6; - --basket-pctfilled-gridRow: 1/5; - --basket-actions-gridColumn: 7; - --basket-actions-gridRow: 1/5; - --basket-takeoffmarket-gridColumn: 7; - --basket-takeoffmarket-gridRow: 1/5; - - - grid-template-columns: auto auto auto auto auto auto 1fr; - } - - .vuuBasketToolbar-sideField.saltFormField-labelTop, - .vuuBasketToolbar-unitsField.saltFormField-labelTop { - grid-template-areas: "label content"; - } - - .vuuBasketToolbar-sideField { - align-self: end; - } - .vuuBasketToolbar-sideField .saltFormFieldLabel, - .vuuBasketToolbar-unitsField .saltFormFieldLabel { - width: 28px; - } - - .vuuBasketToolbar-side { - --saltButton-height: 24px; - } - .vuuBasketToolbar-units { - --vuuExpandoInput-height: 24px; - } - - -} - @container basket-toolbar-live (width < 1450px) { - .vuuBasketToolbar-on-market .vuuBasketToolbar-inner { - --vuuBasketSelector-height: 36px; - --basket-selector-gridRow: 1/3; - --basket-notionalUsd-gridColumn: 4; - --basket-notionalUsd-gridRow: 1/3; - --basket-notional-gridColumn: 4; - --basket-notional-gridRow: 3/5; - --basket-pctfilled-gridColumn: 5; - --basket-pctfilled-gridRow: 1/5; - - --basket-actions-gridColumn: 6; - --basket-actions-gridRow: 1/5; + .vuuBasketToolbar-inner { --basket-takeoffmarket-gridColumn: 1; - --basket-takeoffmarket-gridRow: 3/5; - + --basket-takeoffmarket-gridRow: 5/6; + grid-template-columns: auto auto auto auto auto 1fr; - - } - - .saltFormField-labelTop { - grid-template-areas: "label content"; - } - - .vuuBasketToolbar-notionalField .saltFormFieldLabel, - .vuuBasketToolbar-notionalUsdField .saltFormFieldLabel { - align-self: center; - width: 70px; - } - - .vuuBasketToolbar-notionalField { - margin: 0; } - - .vuuBasketToolbar-notionalField:before { - content: none; - } - - .vuuBasketToolbar-actions { - align-self: center; - } - - + } + diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx index 2f0b4895b..0da37b7f1 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx @@ -6,17 +6,17 @@ import { useEditableText, } from "@finos/vuu-ui-controls"; import { Button, FormField, FormFieldLabel } from "@salt-ds/core"; -import { +import type { CommitResponse, DataItemCommitHandler, -} from "packages/vuu-table-types"; -import { VuuRowDataItemType } from "packages/vuu-protocol-types"; +} from "@finos/vuu-table-types"; +import type { VuuRowDataItemType } from "@finos/vuu-protocol-types"; import { HTMLAttributes, useCallback } from "react"; import { BasketSelector, BasketSelectorProps } from "../basket-selector"; import { Basket } from "../useBasketTrading"; -import { BasketStatus } from "../VuuBasketTradingFeature"; +import type { BasketStatus } from "../VuuBasketTradingFeature"; import { BasketMenu } from "./BasketMenu"; -import cx from "classnames"; +import cx from "clsx"; import "./BasketToolbar.css"; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx index 98e122ddf..bc8b3fa20 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx @@ -1,14 +1,32 @@ +import { + SetPropsAction, + useLayoutProviderDispatch, + useViewContext, +} from "@finos/vuu-layout"; import { registerComponent } from "@finos/vuu-utils"; import { Button } from "@salt-ds/core"; -import { SetPropsAction, useLayoutProviderDispatch } from "@finos/vuu-layout"; -import { MouseEventHandler, useCallback } from "react"; +import type { DataSource } from "@finos/vuu-data-types"; +import type { InstrumentSearchProps } from "@finos/vuu-ui-controls/src"; +import { MouseEventHandler, useCallback, useMemo } from "react"; + import "./ColHeaderAddSymbol.css"; -import { InstrumentSearchProps } from "packages/vuu-ui-controls/src"; const classBase = "vuuColHeaderAddSymbol"; export const ColHeaderAddSymbol = () => { const dispatchLayoutAction = useLayoutProviderDispatch(); + const { loadSession } = useViewContext(); + + const dataSource = useMemo(() => { + const ds = loadSession?.("data-source-basket-constituent") as DataSource; + if (ds) { + return ds; + } else { + throw Error( + "ColHeaderAddSymbol expects Basket Constituent datasource to be available in session store" + ); + } + }, [loadSession]); const handleClick = useCallback( (e) => { @@ -25,14 +43,14 @@ export const ColHeaderAddSymbol = () => { allowDragDrop: "drag-copy", id: "basket-instruments", }, - table: { module: "BASKET", table: "basketConstituent" }, + dataSource, } as InstrumentSearchProps, }, title: "Add Ticker", }, } as SetPropsAction); }, - [dispatchLayoutAction] + [dataSource, dispatchLayoutAction] ); return ( @@ -45,6 +63,6 @@ export const ColHeaderAddSymbol = () => { registerComponent( "col-header-add-symbol", ColHeaderAddSymbol, - "cell-renderer", + "column-header-content-renderer", {} ); diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx index 59752c338..89d73d899 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx @@ -5,7 +5,7 @@ import { isValidNumber, registerComponent, } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import { CSSProperties } from "react"; import "./ProgressCell.css"; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx index e5c754296..ffabfa186 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx @@ -1,6 +1,6 @@ import { TableCellRendererProps } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-utils"; -import cx from "classnames"; +import cx from "clsx"; import "./StatusCell.css"; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx index a205b28bd..1ed45b2da 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx @@ -1,4 +1,4 @@ -import { DataSource, TableSchema } from "@finos/vuu-data"; +import { DataSource, TableSchema } from "@finos/vuu-data-types"; import { DialogHeader, PopupComponent as Popup, @@ -10,7 +10,7 @@ import { VuuInput, } from "@finos/vuu-ui-controls"; import { Button, FormField, FormFieldLabel } from "@salt-ds/core"; -import cx from "classnames"; +import cx from "clsx"; import { DataSourceRow } from "@finos/vuu-data-types"; import { HTMLAttributes, RefCallback, useCallback, useMemo } from "react"; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts index 61178ca34..49ba76c1c 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts +++ b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts @@ -1,8 +1,3 @@ -import { - ClientToServerMenuRPC, - VuuMenu, - VuuMenuItem, -} from "@finos/vuu-protocol-types"; import { TableRowSelectHandler } from "@finos/vuu-table"; import { Commithandler, OpenChangeHandler } from "@finos/vuu-ui-controls"; import { buildColumnMap, metadataKeys } from "@finos/vuu-utils"; @@ -11,25 +6,6 @@ import { NewBasketPanelProps } from "./NewBasketPanel"; const { KEY } = metadataKeys; -type Menu = VuuMenu | VuuMenuItem; -const isMenu = (menu: Menu): menu is VuuMenu => "menus" in menu; -const flatten = (menus: Menu[], menuItems: VuuMenuItem[] = []) => { - menus.forEach((m) => - isMenu(m) ? flatten(m.menus, menuItems) : menuItems.push(m) - ); - return menuItems; -}; -const getRpcCommand = (menus: Menu[], selectRpcCommand?: string) => { - const selectionMenuItems = flatten(menus).filter( - (m) => m.context === "selected-rows" - ); - if (selectRpcCommand) { - return selectionMenuItems.find((m) => m.rpcName === selectRpcCommand); - } else if (selectionMenuItems.length === 1) { - return selectionMenuItems[0]; - } -}; - export type NewBasketHookProps = Pick< NewBasketPanelProps, "basketDataSource" | "basketSchema" | "onSaveBasket" @@ -44,46 +20,29 @@ export const useNewBasketPanel = ({ const [basketName, setBasketName] = useState(""); const [basketId, setBasketId] = useState(); const saveButtonRef = useRef(null); - const saveBasket = useCallback(() => { if (basketName && basketId) { onSaveBasket(basketName, basketId); - if (basketDataSource?.menu) { - const rpcCommand = getRpcCommand( - basketDataSource?.menu?.menus, - "CREATE_NEW_BASKET" - ); - if (rpcCommand) { - basketDataSource - .rpcCall?.({ - namedParams: {}, - params: [basketId, basketName], - rpcName: "createBasket", - type: "VIEW_PORT_RPC_CALL", - }) - .then((response) => { - console.log(`rpcResponse`, { response }); - }); - } - } else { - throw Error( - "useNewBasketPanel cannot create basket, datasource has no menu" - ); - } + basketDataSource + .rpcCall?.({ + namedParams: {}, + params: [basketId, basketName], + rpcName: "createBasket", + type: "VIEW_PORT_RPC_CALL", + }) + .then((response) => { + console.log(`rpcResponse`, { response }); + }); } }, [basketDataSource, basketId, basketName, onSaveBasket]); - const handleSelectBasket = useCallback( - (row) => { - const basketId = row[KEY] as string; - console.log({ basketId, columnMap }); - setBasketId(basketId); - setTimeout(() => { - saveButtonRef.current?.focus(); - }, 60); - }, - [columnMap] - ); + const handleSelectBasket = useCallback((row) => { + const basketId = row[KEY] as string; + setBasketId(basketId); + setTimeout(() => { + saveButtonRef.current?.focus(); + }, 60); + }, []); const handleChangeBasketName = useCallback>( (evt, value) => { diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx index e36dcccec..c07dea64f 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx @@ -1,20 +1,25 @@ import { useVuuMenuActions } from "@finos/vuu-data-react"; -import { DataSourceRow } from "@finos/vuu-data-types"; +import { + DataSourceRow, + SubscribeCallback, + ViewportRpcResponse, +} from "@finos/vuu-data-types"; import { useViewContext } from "@finos/vuu-layout"; -import { buildColumnMap, ColumnMap } from "@finos/vuu-utils"; import { ContextMenuConfiguration, NotificationLevel, useNotifications, } from "@finos/vuu-popups"; +import { buildColumnMap, ColumnMap } from "@finos/vuu-utils"; +import { TableConfig, TableConfigChangeHandler } from "@finos/vuu-table-types"; import { useCallback, useEffect, useMemo, useState } from "react"; import { BasketSelectorProps } from "./basket-selector"; import { BasketChangeHandler } from "./basket-toolbar"; import { NewBasketPanel } from "./new-basket-panel"; import { useBasketTradingDataSources } from "./useBasketTradingDatasources"; import { BasketTradingFeatureProps } from "./VuuBasketTradingFeature"; -import { VuuDataRow, VuuDataRowDto } from "packages/vuu-protocol-types"; -import { SubscribeCallback, ViewportRpcResponse } from "packages/vuu-data/src"; +import defaultEditColumns from "./basket-table-edit/basketConstituentEditColumns"; +import defaultLiveColumns from "./basket-table-live/basketConstituentLiveColumns"; export class Basket { basketId: string; @@ -52,13 +57,6 @@ export type BasketTradingHookProps = Pick< | "basketTradingConstituentJoinSchema" >; -const toDataDto = (dataSourceRow: VuuDataRow, columnMap: ColumnMap) => { - Object.entries(columnMap).reduce((dto, [colName, index]) => { - dto[colName] = dataSourceRow[index]; - return dto; - }, {}); -}; - type BasketState = { basketInstanceId?: string; dialog?: JSX.Element; @@ -75,6 +73,26 @@ export const useBasketTrading = ({ const { load, save } = useViewContext(); const { notify } = useNotifications(); + const editConfig = useMemo(() => { + const config = load?.("basket-edit-table-config") as TableConfig; + return ( + config ?? { + columns: defaultEditColumns, + rowSeparators: true, + } + ); + }, [load]); + + const liveConfig = useMemo(() => { + const config = load?.("basket-live-table-config") as TableConfig; + return ( + config ?? { + columns: defaultLiveColumns, + rowSeparators: true, + } + ); + }, [load]); + const basketConstituentMap = useMemo( () => buildColumnMap(basketConstituentSchema.columns), [basketConstituentSchema] @@ -95,6 +113,7 @@ export const useBasketTrading = ({ } = useBasketTradingDataSources({ basketInstanceId, basketSchema, + basketConstituentSchema, basketTradingSchema, basketTradingConstituentJoinSchema, }); @@ -148,12 +167,15 @@ export const useBasketTrading = ({ })); }, []); - const handleSaveNewBasket = useCallback((basketName, basketId) => { - setBasketState((state) => ({ - ...state, - dialog: undefined, - })); - }, []); + const handleSaveNewBasket = useCallback( + (/*basketName, basketId*/) => { + setBasketState((state) => ({ + ...state, + dialog: undefined, + })); + }, + [] + ); const handleSelectBasket = useCallback( (basketInstanceId: string) => { @@ -251,13 +273,13 @@ export const useBasketTrading = ({ params: [ric], }) .then((response) => { - if (response?.action.type === "VP_RCP_SUCCESS") { + if (response?.action.type === "VP_RPC_SUCCESS") { notify?.({ type: NotificationLevel.Success, header: "Add Constituent to Basket", body: `${ric} added to basket`, }); - } else if (response?.action.type === "VP_RCP_FAILURE") { + } else if (response?.action.type === "VP_RPC_FAILURE") { notify?.({ type: NotificationLevel.Error, header: "Add Constituent to Basket", @@ -270,6 +292,27 @@ export const useBasketTrading = ({ [basketConstituentMap.ric, dataSourceBasketTradingConstituentJoin, notify] ); + // const handleTableConfigChange = useCallback( + // (config) => { + // save?.(config, "table-config"); + // }, + // [save] + // ); + + const handleConfigChangeEdit = useCallback( + (config) => { + save?.(config, "basket-edit-table-config"); + }, + [save] + ); + + const handleConfigChangeLive = useCallback( + (config) => { + save?.(config, "basket-live-table-config"); + }, + [save] + ); + useEffect(() => { dataSourceBasketTradingControl.resume?.(); return () => { @@ -284,8 +327,12 @@ export const useBasketTrading = ({ basketDesignContextMenuConfig, basketSelectorProps, dataSourceBasketTradingConstituentJoin, + editConfig, + liveConfig, onClickAddBasket: handleAddBasket, onCommitBasketChange: handleCommitBasketChange, + onConfigChangeEdit: handleConfigChangeEdit, + onConfigChangeLive: handleConfigChangeLive, onDropInstrument: handleDropInstrument, onSendToMarket, onTakeOffMarket, diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts index b58a5c9f6..cb45f1804 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts +++ b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts @@ -1,11 +1,11 @@ import { useViewContext } from "@finos/vuu-layout"; +import { VuuDataSource } from "@finos/vuu-data-remote"; import { DataSource, DataSourceConfig, - RemoteDataSource, TableSchema, ViewportRpcResponse, -} from "@finos/vuu-data"; +} from "@finos/vuu-data-types"; import { useCallback, useMemo } from "react"; import { BasketTradingFeatureProps } from "./VuuBasketTradingFeature"; import { NotificationLevel, useNotifications } from "@finos/vuu-popups"; @@ -14,16 +14,18 @@ export type basketDataSourceKey = | "data-source-basket" | "data-source-basket-trading-control" | "data-source-basket-trading-search" - | "data-source-basket-trading-constituent-join"; + | "data-source-basket-trading-constituent-join" + | "data-source-basket-constituent"; const NO_CONFIG = {}; export const useBasketTradingDataSources = ({ + basketConstituentSchema, basketSchema, basketInstanceId, basketTradingSchema, basketTradingConstituentJoinSchema, -}: Omit & { +}: BasketTradingFeatureProps & { basketInstanceId: string; }) => { const { notify } = useNotifications(); @@ -63,13 +65,14 @@ export const useBasketTradingDataSources = ({ 100, basketFilter, ], + ["data-source-basket-constituent", basketConstituentSchema, 100], ]; const dataSources: DataSource[] = []; for (const [key, schema, bufferSize, config] of dataSourceConfig) { - let dataSource = loadSession?.(key) as RemoteDataSource; + let dataSource = loadSession?.(key) as VuuDataSource; if (dataSource === undefined) { - dataSource = new RemoteDataSource({ + dataSource = new VuuDataSource({ ...config, bufferSize, viewport: `${id}-${key}`, @@ -83,10 +86,11 @@ export const useBasketTradingDataSources = ({ } return dataSources; }, [ + basketInstanceId, basketSchema, basketTradingSchema, - basketInstanceId, basketTradingConstituentJoinSchema, + basketConstituentSchema, loadSession, id, title, @@ -103,7 +107,7 @@ export const useBasketTradingDataSources = ({ type: "VIEW_PORT_RPC_CALL", }) .then((response) => { - if (response?.action.type === "VP_RCP_FAILURE") { + if (response?.action.type === "VP_RPC_FAILURE") { notify({ type: NotificationLevel.Error, header: "Failed to Send to market", @@ -116,26 +120,32 @@ export const useBasketTradingDataSources = ({ [dataSourceBasketTradingControl, notify] ); - const handleTakeOffMarket = useCallback((basketInstanceId: string) => { - dataSourceBasketTradingControl - .rpcCall?.({ - namedParams: {}, - params: [basketInstanceId], - rpcName: "takeOffMarket", - type: "VIEW_PORT_RPC_CALL", - }) - .then((response) => { - if (response?.action.type === "VP_RCP_FAILURE") { - notify({ - type: NotificationLevel.Error, - header: "Failed to take off market", - body: "Please contact your support team", - }); - console.error(response.action.msg); - } - }); - }, []); + const handleTakeOffMarket = useCallback( + (basketInstanceId: string) => { + dataSourceBasketTradingControl + .rpcCall?.({ + namedParams: {}, + params: [basketInstanceId], + rpcName: "takeOffMarket", + type: "VIEW_PORT_RPC_CALL", + }) + .then((response) => { + if (response?.action.type === "VP_RPC_FAILURE") { + notify({ + type: NotificationLevel.Error, + header: "Failed to take off market", + body: "Please contact your support team", + }); + console.error(response.action.msg); + } + }); + }, + [dataSourceBasketTradingControl, notify] + ); + // Note: we do not need to return the BasketConstituent dataSource, we just stash it + // in session state from where it will be used by the AddInstrument button in Col + // Header return { dataSourceBasket, dataSourceBasketTradingControl, diff --git a/vuu-ui/sample-apps/feature-filter-table/package.json b/vuu-ui/sample-apps/feature-filter-table/package.json index 4bb804700..56e16a730 100644 --- a/vuu-ui/sample-apps/feature-filter-table/package.json +++ b/vuu-ui/sample-apps/feature-filter-table/package.json @@ -29,13 +29,13 @@ "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" }, "engines": { "node": ">=16.0.0" diff --git a/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx b/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx index f3a600af2..d7364af1f 100644 --- a/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx +++ b/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx @@ -1,9 +1,9 @@ -import { TableSchema } from "@finos/vuu-data"; +import { TableSchema } from "@finos/vuu-data-types"; import { FilterTable } from "@finos/vuu-datatable"; import { FlexboxLayout } from "@finos/vuu-layout"; -import { DataSourceStats } from "@finos/vuu-table-extras"; -import cx from "classnames"; import { ContextMenuProvider } from "@finos/vuu-popups"; +import { DataSourceStats } from "@finos/vuu-table-extras"; +import cx from "clsx"; import { useFilterTable } from "./useFilterTable"; import "./VuuFilterTableFeature.css"; diff --git a/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx b/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx index 53940d3af..7ce8937d6 100644 --- a/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx +++ b/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx @@ -1,24 +1,29 @@ import { + MenuActionConfig, + SuggestionFetcher, + useVuuMenuActions, +} from "@finos/vuu-data-react"; +import { + DataSourceFilter, DataSourceVisualLinkCreatedMessage, - isTypeaheadSuggestionProvider, SchemaColumn, TypeaheadSuggestionProvider, VuuFeatureInvocationMessage, -} from "@finos/vuu-data"; -import { MenuActionConfig, useVuuMenuActions } from "@finos/vuu-data-react"; -import { DataSourceFilter } from "@finos/vuu-data-types"; -import { SuggestionFetcher } from "@finos/vuu-data-react"; -import { TableConfig } from "@finos/vuu-table-types"; +} from "@finos/vuu-data-types"; import { Filter } from "@finos/vuu-filter-types"; import { FilterBarProps } from "@finos/vuu-filters"; import { ActiveItemChangeHandler, useViewContext } from "@finos/vuu-layout"; +import { TypeaheadParams } from "@finos/vuu-protocol-types"; import { useShellContext } from "@finos/vuu-shell"; -import { applyDefaultColumnConfig } from "@finos/vuu-utils"; +import { TableConfig, TableConfigChangeHandler } from "@finos/vuu-table-types"; +import { + applyDefaultColumnConfig, + isTypeaheadSuggestionProvider, +} from "@finos/vuu-utils"; import { Button } from "@salt-ds/core"; import { useCallback, useMemo, useRef, useState } from "react"; import { useSessionDataSource } from "./useSessionDataSource"; import { FilterTableFeatureProps } from "./VuuFilterTableFeature"; -import { TypeaheadParams } from "packages/vuu-protocol-types"; const NO_CONFIG: FilterTableConfig = {}; @@ -103,8 +108,8 @@ export const useFilterTable = ({ tableSchema }: FilterTableFeatureProps) => { [save] ); - const handleTableConfigChange = useCallback( - (config: TableConfig) => { + const handleTableConfigChange = useCallback( + (config) => { save?.(config, "table-config"); }, [save] diff --git a/vuu-ui/sample-apps/feature-filter-table/src/useSessionDataSource.ts b/vuu-ui/sample-apps/feature-filter-table/src/useSessionDataSource.ts index 26a09cad9..232cc140b 100644 --- a/vuu-ui/sample-apps/feature-filter-table/src/useSessionDataSource.ts +++ b/vuu-ui/sample-apps/feature-filter-table/src/useSessionDataSource.ts @@ -1,10 +1,10 @@ +import { VuuDataSource } from "@finos/vuu-data-remote"; import { - configChanged, DataSource, DataSourceConfig, - RemoteDataSource, TableSchema, -} from "@finos/vuu-data"; +} from "@finos/vuu-data-types"; +import { configChanged } from "@finos/vuu-utils"; import { useViewContext } from "@finos/vuu-layout"; import { useCallback, useMemo } from "react"; @@ -15,8 +15,10 @@ type SessionDataSourceConfig = { const NO_CONFIG: SessionDataSourceConfig = {}; export const useSessionDataSource = ({ + dataSourceSessionKey = "data-source", tableSchema, }: { + dataSourceSessionKey?: string; tableSchema: TableSchema; }) => { const { id, load, save, loadSession, saveSession, title } = useViewContext(); @@ -38,10 +40,10 @@ export const useSessionDataSource = ({ ); const dataSource: DataSource = useMemo(() => { - let ds = loadSession?.("data-source") as RemoteDataSource; + let ds = loadSession?.(dataSourceSessionKey) as VuuDataSource; if (ds) { console.log( - "%cFilterTableFeature DATA SOURCE IN SESSION STATE", + "%useSessionDataSource DATA SOURCE IN SESSION STATE", "color:red;font-weight:bold;" ); @@ -65,7 +67,7 @@ export const useSessionDataSource = ({ dataSourceConfigFromState?.columns ?? tableSchema.columns.map((col) => col.name); - ds = new RemoteDataSource({ + ds = new VuuDataSource({ bufferSize: 0, // bufferSize: 200, viewport: id, diff --git a/vuu-ui/sample-apps/feature-instrument-tiles/package.json b/vuu-ui/sample-apps/feature-instrument-tiles/package.json index 19b1c2d69..db92cc484 100644 --- a/vuu-ui/sample-apps/feature-instrument-tiles/package.json +++ b/vuu-ui/sample-apps/feature-instrument-tiles/package.json @@ -29,13 +29,13 @@ "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" }, "engines": { "node": ">=16.0.0" diff --git a/vuu-ui/sample-apps/feature-instrument-tiles/src/VuuInstrumentTilesFeature.tsx b/vuu-ui/sample-apps/feature-instrument-tiles/src/VuuInstrumentTilesFeature.tsx index 4200e71fa..e552eb7fe 100644 --- a/vuu-ui/sample-apps/feature-instrument-tiles/src/VuuInstrumentTilesFeature.tsx +++ b/vuu-ui/sample-apps/feature-instrument-tiles/src/VuuInstrumentTilesFeature.tsx @@ -1,10 +1,10 @@ +import { VuuDataSource } from "@finos/vuu-data-remote"; import { DataSource, DataSourceConfig, - RemoteDataSource, + DataSourceFilter, TableSchema, -} from "@finos/vuu-data"; -import { DataSourceFilter } from "@finos/vuu-data-types"; +} from "@finos/vuu-data-types"; import { useViewContext } from "@finos/vuu-layout"; import { buildColumnMap, metadataKeys } from "@finos/vuu-utils"; import { useCallback, useEffect, useMemo } from "react"; @@ -56,13 +56,13 @@ const VuuInstrumentTilesFeature = ({ ); const dataSource: DataSource = useMemo(() => { - let ds = loadSession?.("data-source") as RemoteDataSource; + let ds = loadSession?.("data-source") as VuuDataSource; if (ds) { console.log({ ds }); return ds; } - ds = new RemoteDataSource({ + ds = new VuuDataSource({ bufferSize: 200, viewport: id, table: instrumentPricesSchema.table, diff --git a/vuu-ui/sample-apps/feature-instrument-tiles/src/useDataSource.ts b/vuu-ui/sample-apps/feature-instrument-tiles/src/useDataSource.ts index 4275b2a67..2d2d50aad 100644 --- a/vuu-ui/sample-apps/feature-instrument-tiles/src/useDataSource.ts +++ b/vuu-ui/sample-apps/feature-instrument-tiles/src/useDataSource.ts @@ -1,4 +1,4 @@ -import { DataSource, SubscribeCallback } from "@finos/vuu-data"; +import { DataSource, SubscribeCallback } from "@finos/vuu-data-types"; import { DataSourceRow } from "@finos/vuu-data-types"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { MovingWindow } from "./moving-window"; diff --git a/vuu-ui/sample-apps/feature-template/package.json b/vuu-ui/sample-apps/feature-template/package.json index 5a07fbb94..2dc04f0b8 100644 --- a/vuu-ui/sample-apps/feature-template/package.json +++ b/vuu-ui/sample-apps/feature-template/package.json @@ -29,13 +29,13 @@ "@finos/vuu-table-extras": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", + "@salt-ds/core": "1.13.2", "@salt-ds/lab": "1.0.0-alpha.15" }, "peerDependencies": { - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" }, "engines": { "node": ">=16.0.0" diff --git a/vuu-ui/sample-apps/feature-template/src/VuuTemplateFeature.tsx b/vuu-ui/sample-apps/feature-template/src/VuuTemplateFeature.tsx index 5cbc54377..6d1dfc368 100644 --- a/vuu-ui/sample-apps/feature-template/src/VuuTemplateFeature.tsx +++ b/vuu-ui/sample-apps/feature-template/src/VuuTemplateFeature.tsx @@ -1,9 +1,9 @@ +import { VuuDataSource } from "@finos/vuu-data-remote"; import { DataSource, DataSourceConfig, - RemoteDataSource, TableSchema, -} from "@finos/vuu-data"; +} from "@finos/vuu-data-types"; import { useViewContext } from "@finos/vuu-layout"; import { useCallback, useEffect, useMemo } from "react"; @@ -33,12 +33,12 @@ const VuuTemplateFeature = ({ tableSchema }: FilterTableFeatureProps) => { ); const dataSource: DataSource = useMemo(() => { - let ds = loadSession?.("data-source") as RemoteDataSource; + let ds = loadSession?.("data-source") as VuuDataSource; if (ds) { return ds; } - ds = new RemoteDataSource({ + ds = new VuuDataSource({ bufferSize: 200, viewport: id, table: tableSchema.table, diff --git a/vuu-ui/sample-apps/standalone-table/index.tsx b/vuu-ui/sample-apps/standalone-table/index.tsx new file mode 100644 index 000000000..449802cc1 --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/index.tsx @@ -0,0 +1,5 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import { App } from "./src/App"; + +ReactDOM.render(, document.getElementById("root")); diff --git a/vuu-ui/sample-apps/standalone-table/package.json b/vuu-ui/sample-apps/standalone-table/package.json new file mode 100644 index 000000000..76ba47a41 --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/package.json @@ -0,0 +1,28 @@ +{ + "name": "standalone-table", + "version": "0.0.26", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "node ./scripts/build.mjs", + "build:with-ag-grid": "node ./scripts/build.mjs --features feature-vuu-blotter,feature-ag-grid", + "start": "serve -p 5002 ../../deployed_apps/app-vuu-example" + }, + "keywords": [], + "author": "heswell", + "license": "Apache-2.0", + "sideEffects": [ + "**/*.css" + ], + "devDependencies": {}, + "dependencies": { + "@fontsource/open-sans": "^4.5.13", + "@finos/vuu-table": "0.0.26", + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2" + }, + "engines": { + "node": ">=16.0.0" + } +} diff --git a/vuu-ui/sample-apps/standalone-table/public/index.html b/vuu-ui/sample-apps/standalone-table/public/index.html new file mode 100644 index 000000000..9951cfc38 --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/public/index.html @@ -0,0 +1,14 @@ + + + + + + + + VUU Table + + +
+ + + diff --git a/vuu-ui/sample-apps/standalone-table/scripts/.eslintrc.json b/vuu-ui/sample-apps/standalone-table/scripts/.eslintrc.json new file mode 100644 index 000000000..17388657e --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/scripts/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "env": { + "node": true, + "es2021": true + }, + "extends": ["eslint:recommended", "plugin:react/recommended"], + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": {} +} diff --git a/vuu-ui/sample-apps/standalone-table/scripts/build.mjs b/vuu-ui/sample-apps/standalone-table/scripts/build.mjs new file mode 100644 index 000000000..c8513299d --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/scripts/build.mjs @@ -0,0 +1,107 @@ +import { + byFileName, + copyFolderSync, + formatBytes, + formatDuration, + getCommandLineArg, + padRight, + readPackageJson, + writeMetaFile, +} from "../../../scripts/utils.mjs"; +import { build } from "../../../scripts/esbuild.mjs"; +import fs from "fs"; +import path from "path"; + +const entryPoints = ["index.tsx"]; + +const outdir = "../../deployed_apps/standalone-table"; + +const watch = getCommandLineArg("--watch"); +const development = watch || getCommandLineArg("--dev"); + +const { name: projectName } = readPackageJson(); + +const esbuildConfig = { + entryPoints, + env: development ? "development" : "production", + name: "standalone-table", + outdir, + splitting: true, + target: "esnext", +}; + +async function main() { + function createDeployFolder() { + fs.rmSync(outdir, { recursive: true, force: true }); + fs.mkdirSync(outdir, { recursive: true }); + } + + console.log("[CLEAN]"); + createDeployFolder(); + + console.log("[BUILD]"); + const [ + { + result: { metafile }, + duration, + }, + ] = await Promise.all([build(esbuildConfig)]).catch((e) => { + console.error(e); + process.exit(1); + }); + + await writeMetaFile(metafile, outdir); + + console.log("[DEPLOY public assets]"); + const publicContent = fs.readdirSync(`./public`); + publicContent.forEach((file) => { + if (file !== ".DS_Store") { + if (typeof fs.cp === "function") { + // node v16.7 + + fs.cp( + path.resolve("public", file), + path.resolve(outdir, file), + { recursive: true }, + (err) => { + if (err) throw err; + } + ); + } else { + // delete once we no longer need to support node16 < .7 + copyFolderSync( + path.resolve("public", file), + path.resolve(outdir, file) + ); + } + } + }); + + const outputs = { + core: [], + common: [], + features: [], + }; + for (const [file, { bytes }] of Object.entries(metafile.outputs)) { + if (file.endsWith("js") || file.endsWith("css")) { + const fileName = file.replace(`${outdir}/`, ""); + if (fileName.startsWith(projectName)) { + outputs.core.push({ fileName, bytes }); + } else { + outputs.common.push({ fileName, bytes }); + } + } + } + + console.log("\ncore"); + outputs.core.sort(byFileName).forEach(({ fileName, bytes }) => { + console.log(`${padRight(fileName, 30)} ${formatBytes(bytes)}`); + }); + console.log("\ncommon"); + outputs.common.forEach(({ fileName, bytes }) => { + console.log(`${padRight(fileName, 30)} ${formatBytes(bytes)}`); + }); + + console.log(`\nbuild took ${formatDuration(duration)}`); +} + +main(); diff --git a/vuu-ui/sample-apps/standalone-table/src/App.css b/vuu-ui/sample-apps/standalone-table/src/App.css new file mode 100644 index 000000000..00137527b --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/src/App.css @@ -0,0 +1,8 @@ +body { + margin: 0; +} + +#root { + height: 100vh; + width: 100vw; +} \ No newline at end of file diff --git a/vuu-ui/sample-apps/standalone-table/src/App.tsx b/vuu-ui/sample-apps/standalone-table/src/App.tsx new file mode 100644 index 000000000..2677b9d54 --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/src/App.tsx @@ -0,0 +1,36 @@ +import { Table } from "@finos/vuu-table"; +import { getSchema, SimulTableName, vuuModule } from "@finos/vuu-data-test"; + +// import "@finos/vuu-icons/index.css"; +// import "@finos/vuu-theme/index.css"; + +import "./App.css"; +// import { ThemeProvider } from "@finos/vuu-utils"; + +export const App = () => { + const columnDescriptors = [{ name: "Column 1" }, { name: "Column 2" }]; + // const dataSource = new ArrayDataSource({ + // columnDescriptors, + // data: [ + // ["test1", 1000], + // ["test2", 2000], + // ["test3", 3000], + // ["test4", 4000], + // ["test5", 5000], + // ["test6", 6000], + // ], + // }); + const schema = getSchema("instruments"); + const dataSource = + vuuModule("SIMUL").createDataSource("instruments"); + + const tableConfig = { + columns: schema.columns, + }; + + return ( + // +
+ // + ); +}; diff --git a/vuu-ui/sample-apps/standalone-table/src/table-custom.css b/vuu-ui/sample-apps/standalone-table/src/table-custom.css new file mode 100644 index 000000000..0f9053c52 --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/src/table-custom.css @@ -0,0 +1,3 @@ +.vuuTable { + +} \ No newline at end of file diff --git a/vuu-ui/sample-apps/standalone-table/tsconfig.json b/vuu-ui/sample-apps/standalone-table/tsconfig.json new file mode 100644 index 000000000..409f9488e --- /dev/null +++ b/vuu-ui/sample-apps/standalone-table/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "esnext", + } +} diff --git a/vuu-ui/scripts/build-all-type-defs.mjs b/vuu-ui/scripts/build-all-type-defs.mjs index 4079e1323..2579e02a0 100644 --- a/vuu-ui/scripts/build-all-type-defs.mjs +++ b/vuu-ui/scripts/build-all-type-defs.mjs @@ -11,20 +11,22 @@ function buildPackage(packageName) { } const packages = [ - "vuu-utils", - "vuu-data", - "vuu-data-test", - "vuu-data-react", + "vuu-codemirror", "vuu-data-ag-grid", + "vuu-data-local", + "vuu-data-react", + "vuu-data-remote", + "vuu-data-test", + "vuu-datatable", "vuu-filter-parser", "vuu-filters", + "vuu-layout", "vuu-popups", - "vuu-datatable", + "vuu-shell", "vuu-table", "vuu-table-extras", - "vuu-layout", - "vuu-shell", "vuu-ui-controls", + "vuu-utils", ]; packages.forEach(buildPackage); diff --git a/vuu-ui/scripts/build-all.mjs b/vuu-ui/scripts/build-all.mjs index d13e2e983..9d91e18bd 100644 --- a/vuu-ui/scripts/build-all.mjs +++ b/vuu-ui/scripts/build-all.mjs @@ -1,27 +1,35 @@ -import { execWait, withArgs } from "./utils.mjs"; +import { execWait, getCommandLineArg, withArgs } from "./utils.mjs"; + +const jsonOutput = getCommandLineArg("json", false); export const buildAll = async () => { const buildPackage = async (packageName) => execWait( - `npm run --silent build${withArgs("dev", "cjs", "debug", "license")}`, + `npm run --silent build${withArgs( + "dev", + "cjs", + "debug", + "license", + "json" + )}`, `packages/${packageName}` ); // TODO determine the dependency graph/build order programatically const wave1 = [ - "vuu-data-test", "vuu-data-types", "vuu-table-types", "vuu-filter-types", - "vuu-filter-parser", "vuu-protocol-types", + "vuu-data-test", + "vuu-filter-parser", "vuu-icons", "vuu-utils", "vuu-ui-controls", "vuu-codemirror", "vuu-theme", ]; - const wave2 = ["vuu-data"]; + const wave2 = ["vuu-data-remote", "vuu-data-local"]; const wave3 = ["vuu-filters", "vuu-popups"]; const wave4 = [ "vuu-datatable", @@ -33,6 +41,14 @@ export const buildAll = async () => { "vuu-shell", ]; + if (jsonOutput) { + console.log( + JSON.stringify({ + "package-list": wave1.concat(wave2).concat(wave3).concat(wave4), + }) + ); + } + await Promise.all(wave1.map(buildPackage)); await Promise.all(wave2.map(buildPackage)); await Promise.all(wave3.map(buildPackage)); diff --git a/vuu-ui/scripts/build.mjs b/vuu-ui/scripts/build.mjs index 97d436cb4..8fefc0c58 100644 --- a/vuu-ui/scripts/build.mjs +++ b/vuu-ui/scripts/build.mjs @@ -72,6 +72,7 @@ export default async function main(customConfig) { const debug = getCommandLineArg("--debug"); const development = watch || debug || getCommandLineArg("--dev"); const cjs = getCommandLineArg("--cjs") ? " --cjs" : ""; + const jsonOutput = getCommandLineArg("--json"); const outdir = `${DIST_PATH}/${packageName}${debug ? "-debug" : ""}`; const hasWorker = fs.existsSync(workerTS); @@ -235,7 +236,10 @@ export default async function main(customConfig) { process.exit(1); }); - console.log(`[${scopedPackageName}]`); + const jsonResult = jsonOutput ? { name: scopedPackageName } : undefined; + if (!jsonOutput) { + console.log(`[${scopedPackageName}]`); + } const jsOut = esmOutput?.result.metafile.outputs?.[`${outdir}/esm/index.js`]; const cssOut = @@ -254,15 +258,23 @@ export default async function main(customConfig) { if (cssOut) { relocateCSSToPackageRoot(); - console.log(` \tindex.css: ${formatBytes(cssOut.bytes)}`); + if (jsonResult) { + jsonResult.css = formatBytes(cssOut.bytes); + } else { + console.log(` \tindex.css: ${formatBytes(cssOut.bytes)}`); + } } if (jsOut) { - console.log( - `\tesm/index.js: ${formatBytes(jsOut.bytes)} (${formatDuration( - esmOutput.duration - )})` - ); + if (jsonResult) { + jsonResult.javascript = formatBytes(jsOut.bytes); + } else { + console.log( + `\tesm/index.js: ${formatBytes(jsOut.bytes)} (${formatDuration( + esmOutput.duration + )})` + ); + } } if (cjs) { @@ -279,4 +291,8 @@ export default async function main(customConfig) { } } } + + if (jsonOutput && jsonResult) { + console.log(JSON.stringify(jsonResult)); + } } diff --git a/vuu-ui/scripts/esbuild.mjs b/vuu-ui/scripts/esbuild.mjs index 254020925..39ab88b92 100644 --- a/vuu-ui/scripts/esbuild.mjs +++ b/vuu-ui/scripts/esbuild.mjs @@ -18,7 +18,6 @@ export async function build(config) { target = ["es2020", "chrome79"], write = true, } = config; - return esbuild({ entryPoints, banner, diff --git a/vuu-ui/scripts/launch-table.mjs b/vuu-ui/scripts/launch-table.mjs new file mode 100644 index 000000000..2818a3f16 --- /dev/null +++ b/vuu-ui/scripts/launch-table.mjs @@ -0,0 +1,11 @@ +import { execWait } from "./utils.mjs"; + +export const launchApp = async () => { + const appName = "standalone-table"; + + execWait(`serve -p 3010 ./deployed_apps/${appName}`); + // await execWait("npm run --silent build"); + // await execWait(`npm run --silent build:${buildTarget}${url}`); +}; + +await launchApp(); diff --git a/vuu-ui/scripts/publish.mjs b/vuu-ui/scripts/publish.mjs index 61c7d1ce3..8357f2b90 100644 --- a/vuu-ui/scripts/publish.mjs +++ b/vuu-ui/scripts/publish.mjs @@ -4,7 +4,8 @@ const debug = getCommandLineArg("--debug"); const packages = [ "vuu-codemirror", - "vuu-data", + "vuu-data-local", + "vuu-data-remote", "vuu-data-ag-grid", "vuu-data-react", "vuu-data-test", diff --git a/vuu-ui/scripts/utils.mjs b/vuu-ui/scripts/utils.mjs index 6ec168cea..f29bdc4d7 100644 --- a/vuu-ui/scripts/utils.mjs +++ b/vuu-ui/scripts/utils.mjs @@ -185,7 +185,9 @@ const args = process.argv.slice(2); export const withArgs = (...argNames) => { const commandLineArgs = argNames - .map((arg) => (args.includes("--" + arg) ? ` --${arg}` : "")) + .map((arg) => + args.includes(arg) || args.includes("--" + arg) ? ` --${arg}` : "" + ) .join(""); return commandLineArgs ? ` -- ${commandLineArgs}` : ""; }; diff --git a/vuu-ui/showcase/package.json b/vuu-ui/showcase/package.json index ac4e7527c..47b49d21a 100644 --- a/vuu-ui/showcase/package.json +++ b/vuu-ui/showcase/package.json @@ -19,18 +19,15 @@ "@faker-js/faker": "^8.0.2", "@finos/vuu-data-test": "0.0.26", "@finos/vuu-data-ag-grid": "0.0.26", - "@finos/vuu-datagrid": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15", + "@salt-ds/core": "1.13.2", "@salt-ds/theme": "1.7.1", - "classnames": "^2.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "clsx": "^2.0.0", + "react": ">=17.0.2", + "react-dom": ">=17.0.2", "react-router-dom": "^6.2.1" }, "devDependencies": { diff --git a/vuu-ui/showcase/scripts/preview.mjs b/vuu-ui/showcase/scripts/preview.mjs index 5e501cb7d..913ed19eb 100644 --- a/vuu-ui/showcase/scripts/preview.mjs +++ b/vuu-ui/showcase/scripts/preview.mjs @@ -8,8 +8,8 @@ import "./copy-preview.mjs"; execWait("node ../node_modules/.bin/vite preview"); -console.log(`opening showcase at ${chalk.green("http://127.0.0.1:4173/")} ...`); +console.log(`opening showcase at ${chalk.green("http://localhost:4173/")} ...`); setTimeout(() => { - open("http://127.0.0.1:4173/"); + open("http://localhost:4173/"); }, 1000); diff --git a/vuu-ui/showcase/src/App.tsx b/vuu-ui/showcase/src/App.tsx index 890085558..1c124ee91 100644 --- a/vuu-ui/showcase/src/App.tsx +++ b/vuu-ui/showcase/src/App.tsx @@ -1,24 +1,13 @@ import { Flexbox } from "@finos/vuu-layout"; -import { - Density, - DensitySwitch, - ThemeMode, - ThemeProvider, - ThemeSwitch, -} from "@finos/vuu-shell"; -import { Dropdown } from "@salt-ds/lab"; +import { Tree, TreeSourceNode } from "@finos/vuu-ui-controls"; +import { Density, ThemeMode, ThemeProvider } from "@finos/vuu-utils"; import { Button, Text } from "@salt-ds/core"; -import { IFrame } from "./components"; import { useCallback, useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; -import { Tree, TreeSourceNode } from "@finos/vuu-ui-controls"; +import { IFrame } from "./components"; import "./App.css"; -// export type VuuExample = ((props?: unknown) => ReactElement) & { -// displaySequence?: number; -// }; - export type VuuExample = { (props?: any): JSX.Element; displaySequence: number; @@ -104,7 +93,6 @@ export const App = ({ stories }: AppProps) => { const handleThemeChange = useCallback( (_evt, theme: ThemeDescriptor | null) => { - console.log(`theme change ${theme}`); if (theme) { setTheme(theme); } @@ -153,15 +141,6 @@ export const App = ({ stories }: AppProps) => { }} data-mode="light" > - - - -