From fda487d5fc5d71d2e9916eceee3b25f153405d61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:10:50 -0700 Subject: [PATCH] [site] Display encoded payment request and internal status on received payment d (#395) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [site] Display encoded payment request and internal status on received payment details (#9381) GitOrigin-RevId: e2a4904dfc1c4757003d60745dc34ef0b907f43c * Bump vite from 5.0.5 to 5.0.12 in /js (#9515) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.5 to 5.0.12.
Changelog

Sourced from vite's changelog.

5.0.12 (2024-01-19)

5.0.11 (2024-01-05)

5.0.10 (2023-12-15)

5.0.9 (2023-12-14)

5.0.8 (2023-12-12)

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=vite&package-manager=npm_and_yarn&previous-version=5.0.5&new-version=5.0.12)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/lightsparkdev/webdev/network/alerts).
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Corey Martin GitOrigin-RevId: cc2337a5da920b98923b247bc83cd6619e592065 * CI update lock file for PR * Bump ip from 1.1.8 to 1.1.9 in /js/packages/react-native/examples/ReactNativeWallet (#9528) Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ip&package-manager=npm_and_yarn&previous-version=1.1.8&new-version=1.1.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/lightsparkdev/webdev/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Corey Martin GitOrigin-RevId: 05eb73b692a008a1bc90b40bec17eaf2e665033b * Bump follow-redirects from 1.15.3 to 1.15.6 in /js/packages/react-native/examples/ReactNativeWallet (#9526) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.3 to 1.15.6.
Commits
  • 35a517c Release version 1.15.6 of the npm package.
  • c4f847f Drop Proxy-Authorization across hosts.
  • 8526b4a Use GitHub for disclosure.
  • b1677ce Release version 1.15.5 of the npm package.
  • d8914f7 Preserve fragment in responseUrl.
  • 6585820 Release version 1.15.4 of the npm package.
  • 7a6567e Disallow bracketed hostnames.
  • 05629af Prefer native URL instead of deprecated url.parse.
  • 1cba8e8 Prefer native URL instead of legacy url.resolve.
  • 72bc2a4 Simplify _processResponse error handling.
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.3&new-version=1.15.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/lightsparkdev/webdev/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Zhen Lu GitOrigin-RevId: efc8996c28ad43a53e73950e179a98701df03c6f * Bump jose from 4.15.4 to 4.15.5 in /js (#9537) Bumps [jose](https://github.com/panva/jose) from 4.15.4 to 4.15.5.
Release notes

Sourced from jose's releases.

v4.15.5

Fixes

Changelog

Sourced from jose's changelog.

4.15.5 (2024-03-07)

Fixes

  • add a maxOutputLength option to zlib inflate (1b91d88)
Commits
  • 765aafd chore(release): 4.15.5
  • b36e45e test: add export check to x509 pem import tests
  • e839ecb test: stop testing JWE RSA1_5 Algorithm
  • 1b91d88 fix: add a maxOutputLength option to zlib inflate
  • 9ca2b24 build: remove release action
  • f3035d8 chore: cleanup after release
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=jose&package-manager=npm_and_yarn&previous-version=4.15.4&new-version=4.15.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/lightsparkdev/webdev/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Zhen Lu GitOrigin-RevId: 0faad175d4f41811ffd13291e33d597112d983f6 * CI update lock file for PR * Update semver to 7.6.0 (#9540) GitOrigin-RevId: fb7e5ddc926e85500ce9287a9a518919f9ad13d7 * Update the JS demo vasp to 0.8.1 uma sdk. (#9543) GitOrigin-RevId: ec6e16c43795dc20ad611badb163293f627d7aed * CI update lock file for PR * Bump the uma vasp sdk version to 0.8.2 (#9563) GitOrigin-RevId: f1ecccbf1c7df5adfe3a5c5817d85afd0c3c9501 * CI update lock file for PR * [docs] add uma introduction video (#9569) GitOrigin-RevId: ea7dd4c5e29bfb4d59eec4ca4965295165f3d119 * Add multi capability to IdFilter and StringFilter (#9458) ![Screenshot 2024-03-14 at 5.11.23 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/eb50627e-a84b-4da6-8ec3-a6d0c68393c0.png) - allows user to apply multiple values for a filter - they can be deleted via buttons that appear below the filter - fixes column mapping to be snake case due to Filter using a generic type for column keys - adds queryVariable to IdFilter and StringFilter due to column names not necessarily mapping to a query variable name GitOrigin-RevId: 104f6c41f87905adfdf173c1ffb96d14f908590f * Add Badge themes and add badges to webhook log (#9467) ![Screenshot 2024-03-15 at 5.24.06 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/7dc57862-76c7-4e87-aeab-e0ab773a0fbf.png) ![Screenshot 2024-03-15 at 5.23.59 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/82174f64-e191-45f5-a610-9ce032869908.png) - updates badge to have error theme - adds http code badge to webhook log - adds Unverified badge if response_error_code says so - updates colors in webhook log details modal - adds num attempts to status in details GitOrigin-RevId: 139c89196eb6d736bd4f8d83dd746f3ca74b78b4 * Bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /js/packages/react-native/examples/ReactNativeWallet (#9582) Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
Release notes

Sourced from webpack-dev-middleware's releases.

v5.3.4

5.3.4 (2024-03-20)

Bug Fixes

  • security: do not allow to read files above (#1779) (189c4ac)
Changelog

Sourced from webpack-dev-middleware's changelog.

5.3.4 (2024-03-20)

Bug Fixes

  • security: do not allow to read files above (#1779) (189c4ac)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=webpack-dev-middleware&package-manager=npm_and_yarn&previous-version=5.3.3&new-version=5.3.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/lightsparkdev/webdev/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Zhen Lu GitOrigin-RevId: e0739a0a0de84ff1eb34888bd63f6f954de1cefd * [ops] move ops inspector search to header, fix search button (#9639)
🎥 Video uploaded on Graphite:
- fixes search button not working due to react select clearing input on blur - moves search to header - search can be opened via button or shortcut - entering a search or pressing escape or clicking the close button closes it - chose to not use Modal because Modal would unload the search which was performing the query and unexpected behavior would happen - always shows ops tools search now - shows description when no results are found GitOrigin-RevId: ec385e7688f8f169e08137a764e8e0fd53b6d505 * Update UMA integration tests to include V1 images. (#9510) GitOrigin-RevId: f10be54533e2f9ee15869ad43364b8ec68ac03ab * Update the vasp CLI tool for umav1 (#9840) GitOrigin-RevId: d01400b51443f2eafed91535ab8005cf7678d8ea * Update the demo vasp to use uma 1.0 (#9218) Co-authored-by: Jeremy Klein GitOrigin-RevId: f7ce53846cebe620363ab18b7043444c059aa614 * CI update lock file for PR * Update demo vasp to use post-tx callback utils and verify signature (#9880) GitOrigin-RevId: 9388b086325a5af3fd3b0cb6754cba74c24a2530 * [ui] Move PageSectionNav to new UI component (#9971) For use in @dawit-0 's PR https://github.com/lightsparkdev/webdev/pull/9965 GitOrigin-RevId: dd3ef4035304de8d6ab5f2d83d23b53062ffa284 * [ui] Move all PageSection components and Dropdown to public UI (#9979) For use in @dawit-0 's PR https://github.com/lightsparkdev/webdev/pull/9965 GitOrigin-RevId: 9d1a8a36c12ddfa060540fc556cf390c11329df1 * [js] Upgrade Apollo (#10052) GitOrigin-RevId: eb13b6a84a080eaaa4322e3a080b005501bd37a4 * CI update lock file for PR * [ui] Allow Modal submit to be a link (#10066) GitOrigin-RevId: 5127ae88434d30692d0456e5ddb652373f974bd8 * [transactions_report] Remove time filter for reporting (#10107) Added isDateOnly to props to have to option to have date only filters https://github.com/lightsparkdev/webdev/assets/132481249/50046b5d-073f-4c7e-88aa-48b1478aea81 GitOrigin-RevId: 09b9cee9e29ee46262e74e50c2b6680ab3dc50c6 * CI update lock file for PR * Update readmes related to uma certs (#10139) GitOrigin-RevId: 2c578459c89c4365ffc29a7a10ce4d202735bb52 * [uma-bridge] Initial Plaid integration (#10146) GitOrigin-RevId: fc9083ee22ba6b6aa0927d927c317d0ab2b6b063 * [ui] Move themes to own file. Simplify colors (#10167) GitOrigin-RevId: 1d968ccb6f4e09e11893aa0d5d6f9f90f8cd83cf * [ui] Move typography and tokens (#10172) GitOrigin-RevId: 729f9d839fc6224005d97c185c01a464dac715ba * [ui] Improve theme typography tokens and add bridge tokens (#10189) GitOrigin-RevId: bc77c6e38d0a6491161299b41e76f24e8ce08c30 * [ui] Move typography to components (#10178) GitOrigin-RevId: afc3b60e25df2f727511d088f72c285bf8fd4acf * Create wise-tables-knock.md * [ui] Remove unused icons (#10179) GitOrigin-RevId: 117054dfc2879c55c816e22238ebef0fbcddca53 * Some vasp cli fixes for sender-locked amounts (#10207) GitOrigin-RevId: a09da053b1d4af84fc33cbe3e0061402cb6b224c * [ui] Preload icons. Switch to ui/src path for imports (#10182) GitOrigin-RevId: e3e4b5e05cf13267d7764afddba097e94e402cff * [static] Add new static workspace and upload to S3 (#10230) GitOrigin-RevId: 33332dbf54e2fbb3851fdaadb609111fef1833c2 * [colors] fix invalid color string (#10231) umame docs make heavy usage of this color and as a result made the headline link color blue GitOrigin-RevId: 7b3d99bccf884bb9443e87fd62bbf3eb54dbf1d0 * [js] Dummy change to trigger build GitOrigin-RevId: f1255918f6317ac8d05896eb2cae6ab8b1c97806 * [uda] Initial working version of UDA (#10198) Squashed branch of commits/PRs reviewed by various people: https://github.com/lightsparkdev/webdev/pull/10197 https://github.com/lightsparkdev/webdev/pull/10175 https://github.com/lightsparkdev/webdev/pull/10173 https://github.com/lightsparkdev/webdev/pull/10159 https://github.com/lightsparkdev/webdev/pull/10121 https://github.com/lightsparkdev/webdev/pull/10118 https://github.com/lightsparkdev/webdev/pull/10090 https://github.com/lightsparkdev/webdev/pull/10084 https://github.com/lightsparkdev/webdev/pull/10064 https://github.com/lightsparkdev/webdev/pull/10062 https://github.com/lightsparkdev/webdev/pull/10037 https://github.com/lightsparkdev/webdev/pull/10001 https://github.com/lightsparkdev/webdev/pull/10000 https://github.com/lightsparkdev/webdev/pull/9999 https://github.com/lightsparkdev/webdev/pull/9998 https://github.com/lightsparkdev/webdev/pull/9935 https://github.com/lightsparkdev/webdev/pull/9912 https://github.com/lightsparkdev/webdev/pull/9911 GitOrigin-RevId: d7cd34040709c6623ac490c0be5a5546f3169cb6 * Support non-uma receiver in demo vasp (#10225) GitOrigin-RevId: 9fd653e96403fb12debb1e7c40e4bf22243d1f24 * [site] Improve balance tooltips and messaging (#10236) More context: https://lightsparkgroup.slack.com/archives/C03RAD5U336/p1713909385513359 - Add the same available balance messaging tooltip to Send that we have for Withdraw - Add a link to the docs balances page to the tooltip for Send/Withdraw - Add fee estimate text to "Add Funds" to help the user deposit the correct amount. Screenshot 2024-04-24 at 1 03 46 PM Screenshot 2024-04-24 at 1 04 25 PM GitOrigin-RevId: baa54a54c58b6d4902029ee0762d57d55151ec5d * [gha] release: Check that frontend version exists before deploying Add `deploy.py --check` option which just checks that the expected number of files exist. GitOrigin-RevId: 9fa6ee664d44fc6467e0066d24dd44a0d4e9c438 * [ui] Fix InfoIconTooltip debugging prop (#10261) GitOrigin-RevId: 9fce392f0e807ad3019506a4743231e1eee0107f * [ops] migrate channels connection page to DataManagerTable, add Radio ui component, add BooleanFilter (fixes LIG-5141) (#10350) ![Screenshot 2024-04-29 at 6.38.44 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/01da2917-552f-4797-888d-4288b62aa482.png) ![Screenshot 2024-04-29 at 6.38.49 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/362899aa-3de3-4a41-9d89-03b343fbc6be.png) - added a story ![Screenshot 2024-04-30 at 6.39.37 AM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/4d2c0bfb-bd4b-4e33-8ec3-211f6d5c985f.png) GitOrigin-RevId: 059ce5d28462bf0b50ed62fe4624705b37fa48b7 * [bridge] Separate bank / KYC pages (#10262) GitOrigin-RevId: 5ecfc3772b3e5f31744f694b2743d4b623aa8a3e * [ui] Typography improvements (#10331) - Moving towards two possible props for typography content, `content` which can be ToReactNodesArgs, and `children` which can only be a string. This way we keep the typography directly paired with text elements and prevent redundant/problematic styles from leaking in. - Start moving towards new ThemeOrColorKey as base allowed color props for components. Components that want to limit the color further can choose a subset. Base components will call getColor to resolve the color string. Both keys from theme object and colors object are valid choices. - Start moving towards NewRoutesType to replace having to pass in RoutesType to each component that references Routes. Uses global interface augmentation instead - downstream app is expected to extend NewRoutesType. GitOrigin-RevId: c2f210d3cf34a2c845615c1f28a0cd05fe82592b * [ui] Convert Label (#10436) GitOrigin-RevId: fa2041f1aef33e3e149b7460d5a61253a3b6dce8 * Added some basic action scraping to Github bot. (#10482) Created a basic Github client, added some basic methods for scraping actions, and console.log success rate. Contributes to LIG-5259 . GitOrigin-RevId: b92a85b7d11056ac94c975b315e1d4b5dfaa94ed * [site] Allow full precision BTC display amounts (#10489) GitOrigin-RevId: 491e0fb2a10a8ac9c7a490117cb02c9345e21e38 * [ui] Add NextLink as a ToReactNode type (#10432) Make it possible for Next projects to use base typography components directly for consistency. See alse: - https://github.com/vercel/next.js/issues/46078#issuecomment-1920149196 - https://github.com/chakra-ui/chakra-ui/issues/7363#issuecomment-1449395561 - https://github.com/vercel/next.js/discussions/15560 GitOrigin-RevId: 1acc75f8719ee21bd010d797bb7b8feece4f3e5d * [ui] Updated banner style (#10434) GitOrigin-RevId: b3670c7ba4957588bc0bf131333119c0a9742820 * [uma-bridge] Start page (#10485) GitOrigin-RevId: eb72e7370bacc6c2ec1a72196b209b984da4f8eb * [site] Fix z-index for some Banner types (#10535) GitOrigin-RevId: e79f7507d7ec9908667e69fe340f572120993268 * [ui] Button improvements (#10507) - Consolidate button variants into available "kinds" like primary, secondary (remains the default), ghost, and other specific allowed colors. - Start moving towards theme default button props. The button kinds will likely have corresponding default colors at some point to make the kinds customizable across themes. - The concept of button size is now primarily linked to typography size. - Map existing buttons to new prop interface. - Update storybook with new prop interface. https://github.com/lightsparkdev/webdev/assets/4000247/d78c3436-fb04-4206-8260-dbabe95aaa6b GitOrigin-RevId: b3a41d4f0a67f298f89b3ad2065cb166153471a6 * [uma-bridge] Update to latest typography tokens (#10536) GitOrigin-RevId: ef109a2f511697f5295e00c915ae8a798f96df6d * [js] Upgrade codegen (#10537) Upgrade to latest so that we can get react-query v5 compatibility GitOrigin-RevId: 489465d911cf6210c7173b6e0cb9955a6997e35d * [js-sdk] Compress requests with deflate GitOrigin-RevId: 15f01a9cd9445905110c3146255595196543db8f * [js] Move and rename transformGQLName (#10592) GitOrigin-RevId: 31f502ba805ec1a1844cb1f12f8a17d072ae9fb5 * [site] Complete new account creation (#10562) GitOrigin-RevId: 91233a51d55480c8c5f23ff0b408a7ab96cdf7f5 * Adding UX guidelines to Uma.me (#10572) https://linear.app/lightsparkdev/issue/LIG-5436/add-uma-ux-recommendations-to-uma-site GitOrigin-RevId: 5617ffa9fbaca2eeb70d888de1e5ba664e7f1f2f * [ui] Provide icon color inversion when color is specified (#10630) GitOrigin-RevId: 7d67d71d8f96ae5a55777dd6034903b5dc962984 * [site] Re-enable UI tests (#10627) GitOrigin-RevId: 0c8e25ebb825d94def1162cc5a032d5858f8ec0a * [uma-bridge] Configure GQL client with react-query (#10538) GitOrigin-RevId: c03693673e5137816ef635b7b35f7ae568a9a37a * Feature flag new ui in SelectPlan page, add icons (#10618) GitOrigin-RevId: 1fd4a9be8a178e0558aff65fc0ac667d0977d589 * [uma-bridge] Autocomplete hint for account creation and invalid token screen (#10668) GitOrigin-RevId: cc0785596ff7b120e73fe4fb6079d675c9d68b6f * [ui/docs] add Headline ExtraSmall design token, handle h4 and h5 in docs (#10698) ![Screenshot 2024-05-17 at 11.01.28 AM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/95b72bf2-9a25-4c3a-aa57-40983622f48a.png) GitOrigin-RevId: 17f961241d2f048d94f73f47e287f68987deabdc * [site] Ignore ResizeObserver errors in Cypress (#10701) GitOrigin-RevId: c565e89edf49b23bea84930292176b1fa2905405 * [uma-bridge] SecureAccountMFA page (#10702) GitOrigin-RevId: 68a76a42557b986f074b8cf79fd0ba95724d878a * [ui] Fix theme settings (#10734) GitOrigin-RevId: 410f27d46858e1106f57a0affc444b2f2c3d1b02 * [uma-bridge] Login (#10732) GitOrigin-RevId: 005da974e3a71739221d8f2292273dfdc982d71d * [uma-bridge] GetUma page (#10741) Screenshot 2024-05-21 at 11 29 39 PM Screenshot 2024-05-21 at 11 29 30 PM GitOrigin-RevId: 6c0d664602a8912a03874269150d9a957d87dfa5 * [uma-bridge] FAQ page (#10753) GitOrigin-RevId: 13e5e722db57bb4802893ed7a8ffdc1b7ab609f9 * [uma-bridge] Banner progress state (#10757) GitOrigin-RevId: dbee2baff1a8177d4103c77502fecb21fba180c4 * [uma-bridge] Desktop Banner styles (#10778) GitOrigin-RevId: fa3dc43e872d5490121d6fcb08cf1b5350e37688 * [uma-bridge] account page initial setup (#10822) GitOrigin-RevId: 1706fd0afbfb511607880d57325ef667027d0dde * [uma-bridge] Add themed Loading component (#10834) GitOrigin-RevId: 2cb127589b2e9b74f1d8fd8465b6f165ec9f3229 * [ui/bridge] add common Drawer component, optionally use in Modal (#10819) contributes to LIG-5481 - adds having trouble modal/drawer for bridge - makes drawer animation smoother - adds drawer opening animation - transitions background opacity when moving drawer - calculates percentage of drawer closed and closes if let go under 80% - adds drawer as an optional view for Modal - adds horizontal and vertical button layouts - adds extra actions prop to Modal so buttons can be laid out properly ![Screenshot 2024-05-24 at 2.44.36 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/54d5868e-d1b1-44e9-acb6-0a8e2c67ed02.png) ![Screenshot 2024-05-24 at 2.44.18 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/0fcf517b-c2bc-4b25-947d-bbde4c5449df.png) - updates modal to use typography - removes blur from background to be consistent with drawer - moves close button to right side to be consistent old: ![Screenshot 2024-05-24 at 1.45.53 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/3aa0aba3-6b46-4a13-9c94-bb560e9697ec.png) new: ![Screenshot 2024-05-24 at 1.45.57 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/2271a936-e1f2-4081-8dd9-51a1afd5efb3.png) GitOrigin-RevId: e3c5b82e1388c22116ade414328df797256bf6fc * [uma-bridge] Support buttons styling, update gql query (#10885) GitOrigin-RevId: 257674f0d7995eaaa4ae59e58d6c07a8a8657177 * [uma-bridge] Fix logged in desktop header styles (#10839) GitOrigin-RevId: 7213101734cf614763d140c6bebed3d032852b4e * [uma-bridge] Card header styles (#10842) GitOrigin-RevId: d3d3e9eabbea9881e602f968f102e1f6399b8a77 * [uma-bridge] Payment settings styling, use real bank info (#10895) GitOrigin-RevId: 9299391b81212a53b2d3d91b449428fedbe6e249 * [uma-bridge] add log out button to help modal/drawer, add more help modals, show cardform when closing zerohash iframe (#10894) - adds help modal/drawers for plaid and zerohash - shows verify cardform when closing zerohash iframe via clicking background (which doesn't fire a post message) - adds verify icon to verify cardform (note: we'll have to update icons to match the designs) - adds log out button to help modal/drawers - removes temporary log out button from banner ![Screenshot 2024-05-29 at 6.14.13 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/1eb0775e-5e2a-48d7-b9e3-f4c9b595a72b.png) ![Screenshot 2024-05-29 at 6.14.24 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/dd53d76b-7d48-4d03-8d8c-08e58c214878.png) ![Screenshot 2024-05-29 at 5.27.39 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/14498fb7-8563-4367-81a5-0dd099f2a3fa.png) ![Screenshot 2024-05-29 at 5.31.31 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/fa850348-24d6-4819-b464-440c1dc57954.png) ![Screenshot 2024-05-29 at 5.48.09 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/e52a03f7-d476-49e7-814f-e719eb7d587c.png) ![Screenshot 2024-05-29 at 5.48.18 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/NU8OmLauzLqa61yWDJkY/56b03cbd-d3a9-47bb-b212-82dc48b60c7e.png) GitOrigin-RevId: 1aea90dca2ef6182eea8faee5bc76ea4eb3cfa6c * [uma-bridge] add abstraction for help modal data (#10905) GitOrigin-RevId: 724b386c3348f1606b5d48b1150e081973f46b7c * [site] Show msats on TransactionDetails page (#10955) GitOrigin-RevId: 936fcec0783f52b626f182e1451b6e5b11d1a8be * Add frontend Recapcha v3 support for account creation (#10922) Give our recent account creation spam, we probably should have a Recaptcha barrier on our frontend, at least at account creation. This adds frontend support for Recaptcha, but notably does not send it to the backend yet. This will let us at least monitor on the Google console in production. https://linear.app/lightsparkdev/issue/LIG-5555/front-end-recaptcha-implementation GitOrigin-RevId: 01fd543a5b989c6847f82ee9d6bc056d738122cd * [uma-bridge] Display KYC rejected state on VerifyIdentity (#10940) GitOrigin-RevId: c617e9bbde6ce68c1fe727a6922d7ea13f61706b * [ui-test-app] Remove private dependency (#10968) GitOrigin-RevId: 83ba9544bbae30f56e1a7a79f6f1dac3355bdf8c * CI update lock file for PR * trigger change * [uma-vasp] Upgrade UMA core version and fix type issue (#10980) GitOrigin-RevId: 39aaf2d9ad0c8f6e7dadd9b9a83556c693391836 * CI update lock file for PR * [js] Move deploy script to private (#10982) GitOrigin-RevId: f203851612d88b1edcce8aad447bdae299b04ac7 * Create warm-vans-change.md * Create wild-beans-suffer.md * Update from public js-sdk main branch (#9385) Update public `js` sources with the latest code from the [public repository](https://github.com/lightsparkdev/js-sdk) main branch. This typically happens when new versions of the SDK are released and version updates need to be synced. The PR should be merged as soon as possible to avoid updates to webdev overwriting the changes in the js-sdk develop branch. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Lightspark Eng Co-authored-by: Corey Martin GitOrigin-RevId: cb8a90d247c07874ebde3b5e8206fc3b8bca9e05 * CI update lock file for PR * [ui-test-app] Remove GlobalErrorBoundary private dep (#10990) GitOrigin-RevId: 3ac0de5c85e4db08f81c84123bfc43c36424013f --------- Signed-off-by: dependabot[bot] Co-authored-by: Corey Martin Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Lightspark Eng Co-authored-by: Zhen Lu Co-authored-by: Jeremy Klein Co-authored-by: Brian Siao Tick Chong Co-authored-by: Shreya Vissamsetti Co-authored-by: Dawit <132481249+dawit-0@users.noreply.github.com> Co-authored-by: Michael Gorven Co-authored-by: Matthew Rheaume Co-authored-by: Peng Ying Co-authored-by: Joel Weinberger Co-authored-by: lightspark-ci-js-sdk[bot] <134011073+lightspark-ci-js-sdk[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- .changeset/warm-vans-change.md | 23 + .changeset/wild-beans-suffer.md | 6 + .changeset/wise-tables-knock.md | 12 + apps/examples/oauth-app/package.json | 2 +- apps/examples/oauth-app/src/index.tsx | 2 +- .../oauth-app/src/pages/DashboardPage.tsx | 2 +- .../oauth-app/src/pages/LoginPage.tsx | 2 +- apps/examples/react-wallet-app/package.json | 2 +- .../src/components/Dashboard.tsx | 2 +- apps/examples/react-wallet-app/src/index.tsx | 2 +- .../src/pages/DashboardPage.tsx | 6 +- .../react-wallet-app/src/pages/LoginPage.tsx | 15 +- apps/examples/settings.json | 3 + .../streaming-wallet-extension/package.json | 2 +- .../streaming-wallet-extension/src/App.tsx | 7 +- .../src/components/CirclePlusIcon.tsx | 19 - .../src/components/LeftArrow.tsx | 21 - apps/examples/ui-test-app/.eslintrc.js | 23 + apps/examples/ui-test-app/.prettierignore | 1 + apps/examples/ui-test-app/.prettierrc | 3 + apps/examples/ui-test-app/gql-codegen.yml | 11 + apps/examples/ui-test-app/index.html | 43 + .../examples/ui-test-app}/jest.config.ts | 3 - apps/examples/ui-test-app/jest/setup.ts | 23 + .../ui-test-app/jest/setupAfterEnv.ts | 1 + apps/examples/ui-test-app/package.json | 98 + .../ui-test-app/public/favicon-16.ico | Bin 0 -> 4286 bytes .../ui-test-app/public/favicon-32.ico | Bin 0 -> 16958 bytes apps/examples/ui-test-app/public/logo192.png | Bin 0 -> 2211 bytes apps/examples/ui-test-app/public/logo512.png | Bin 0 -> 7413 bytes .../examples/ui-test-app/public/manifest.json | 25 + apps/examples/ui-test-app/public/robots.txt | 3 + apps/examples/ui-test-app/src/Root.tsx | 79 + apps/examples/ui-test-app/src/index.tsx | 18 + .../ui-test-app/src/tests/Banner.test.tsx | 60 + .../ui-test-app/src/tests/CodeInput.test.tsx | 154 + .../src/tests/CommaNumberInput.test.tsx | 213 + .../src/tests/TextIconAligner.test.tsx | 43 + .../ui-test-app/src/tests/Toasts.test.tsx | 62 + .../src/tests/renderTypography.test.tsx | 9 + .../src/tests/toReactNodes.test.tsx | 328 ++ apps/examples/ui-test-app/src/types.ts | 12 + .../examples/ui-test-app}/tsconfig-test.json | 1 + apps/examples/ui-test-app/tsconfig.json | 9 + apps/examples/ui-test-app/vite.config.ts | 8 + apps/examples/uma-vasp-cli/package.json | 2 +- apps/examples/uma-vasp-cli/src/index.ts | 111 +- apps/examples/uma-vasp/README.md | 8 +- apps/examples/uma-vasp/package.json | 4 +- apps/examples/uma-vasp/server.test.ts | 13 +- apps/examples/uma-vasp/src/ReceivingVasp.ts | 227 +- apps/examples/uma-vasp/src/SendingVasp.ts | 332 +- .../uma-vasp/src/SendingVaspRequestCache.ts | 10 +- apps/examples/uma-vasp/src/UmaConfig.ts | 4 + apps/examples/uma-vasp/src/UserService.ts | 2 +- apps/examples/uma-vasp/src/currencies.ts | 11 + .../uma-vasp/src/demo/DemoUserService.ts | 25 +- .../demo/InMemorySendingVaspRequestCache.ts | 45 +- .../src/networking/expressAdapters.ts | 7 + apps/examples/uma-vasp/src/rawLnurl.ts | 11 - apps/examples/uma-vasp/src/server.ts | 54 +- apps/examples/uma-vasp/src/startServer.ts | 5 +- apps/examples/uma-vasp/test.sh | 34 +- package.json | 5 +- packages/core/src/requester/Requester.ts | 49 +- packages/core/src/utils/currency.ts | 76 +- packages/core/src/utils/types.ts | 6 + packages/eslint-config/base.js | 5 +- packages/eslint-config/react-app.js | 2 - packages/lightspark-cli/package.json | 2 +- packages/lightspark-sdk/src/env.ts | 6 +- .../components/CurrencyAmount.tsx | 107 - .../components/Dashboard.tsx | 2 +- .../ReactNativeWallet/package-lock.json | 90 +- .../examples/ReactNativeWallet/package.json | 3 +- .../ReactNativeWallet/utils/currency.ts | 483 --- packages/static/images/lightspark-logo.svg | 55 + packages/static/package.json | 8 + packages/ui/CHANGELOG.md | 4 +- packages/ui/README.md | 2 +- packages/ui/esbuild-svgr-plugin.ts | 54 + packages/ui/package.json | 39 +- packages/ui/src/components/Badge.tsx | 27 +- packages/ui/src/components/Banner/Banner.tsx | 254 ++ .../ui/src/components/Banner/constants.ts | 2 + packages/ui/src/components/Button.tsx | 585 +-- packages/ui/src/components/CardPage.tsx | 2 +- packages/ui/src/components/Checkbox.tsx | 81 + packages/ui/src/components/CodeBlock.tsx | 3 +- .../ui/src/components/CodeInput/CodeInput.tsx | 440 +++ .../components/CodeInput/SingleCodeInput.tsx | 121 + packages/ui/src/components/Collapsible.tsx | 21 +- .../ui/src/components/CommaNumberInput.tsx | 131 + packages/ui/src/components/ContentTable.tsx | 2 +- .../src/components/CopyToClipboardButton.tsx | 9 +- packages/ui/src/components/CurrencyAmount.tsx | 19 +- packages/ui/src/components/Drawer.tsx | 209 + packages/ui/src/components/Dropdown.tsx | 498 +++ packages/ui/src/components/FileInput.tsx | 2 +- packages/ui/src/components/Icon.tsx | 115 - packages/ui/src/components/Icon/Icon.tsx | 107 + packages/ui/src/components/Icon/types.tsx | 3 + .../ui/src/components/InfoIconTooltip.tsx | 30 + .../ui/src/components/LightsparkProvider.tsx | 2 +- packages/ui/src/components/Loading.tsx | 6 +- packages/ui/src/components/Modal.tsx | 280 +- .../components/PageSection/PageSection.tsx | 426 ++ .../components/PageSection/PageSectionNav.tsx | 100 + .../src/components/PageSection/constants.tsx | 1 + packages/ui/src/components/PhoneInput.tsx | 126 + packages/ui/src/components/Pill.tsx | 7 +- packages/ui/src/components/ProgressBar.tsx | 2 +- packages/ui/src/components/Radio.tsx | 60 + packages/ui/src/components/TextButton.tsx | 151 + .../ui/src/components/TextIconAligner.tsx | 44 +- packages/ui/src/components/TextInput.tsx | 399 ++ packages/ui/src/components/Toasts.tsx | 429 ++ packages/ui/src/components/Toggle.tsx | 115 + .../{LightTooltip.tsx => Tooltip.tsx} | 18 +- .../documentation/AnchorLinkHeader.tsx | 35 +- .../documentation/DocsBodyParagraph.tsx | 21 + .../documentation/DocsBodyStrongParagraph.tsx | 31 + .../documentation/DocsHeadline.tsx} | 80 +- .../ui/src/components/documentation/Video.tsx | 20 + packages/ui/src/components/index.tsx | 55 +- .../typography/Article.tsx | 66 +- .../ui/src/components/typography/Body.tsx | 57 + .../src/components/typography/BodyStrong.tsx | 52 + .../ui/src/components/typography/Code.tsx | 48 + .../ui/src/components/typography/Display.tsx | 58 + .../ui/src/components/typography/Headline.tsx | 80 + .../ui/src/components/typography/Label.tsx | 49 + .../components/typography/LabelModerate.tsx | 49 + .../src/components/typography/LabelStrong.tsx | 53 + .../ui/src/components/typography/Overline.tsx | 49 + .../ui/src/components/typography/Title.tsx | 52 + .../ui/src/components/typography/index.tsx | 13 + .../typography/renderTypography.tsx | 43 + packages/ui/src/hooks/useDebounce.tsx | 31 + packages/ui/src/hooks/useResizeObserver.tsx | 85 + packages/ui/src/icons/AI.tsx | 4 +- packages/ui/src/icons/AnchorLink.tsx | 4 +- packages/ui/src/icons/ApiConnection.tsx | 32 +- packages/ui/src/icons/AppIcon.tsx | 4 +- packages/ui/src/icons/ArrowCircle.tsx | 23 + packages/ui/src/icons/ArrowCircleTier1.tsx | 4 +- packages/ui/src/icons/ArrowCircleTier2.tsx | 4 +- packages/ui/src/icons/ArrowCircleTier3.tsx | 4 +- .../ui/src/icons/ArrowCornerDownRight.tsx | 7 +- packages/ui/src/icons/ArrowDown.tsx | 2 - packages/ui/src/icons/ArrowUp.tsx | 2 - .../ui/src/icons/ArrowUpRightCircleFill.tsx | 20 + packages/ui/src/icons/Bank.tsx | 20 + packages/ui/src/icons/Bell.tsx | 30 - packages/ui/src/icons/BellOn.tsx | 37 - packages/ui/src/icons/BitcoinB.tsx | 36 +- .../ui/src/icons/BitcoinBOnRoundedSquare.tsx | 36 +- packages/ui/src/icons/Bolt.tsx | 80 - packages/ui/src/icons/Camera.tsx | 24 - packages/ui/src/icons/CameraCapture.tsx | 4 +- packages/ui/src/icons/CaretRight.tsx | 20 + .../ui/src/icons/CentralArrowShareRight.tsx | 2 - packages/ui/src/icons/Channel.tsx | 33 - packages/ui/src/icons/ChannelBalance.tsx | 27 - packages/ui/src/icons/ChannelOpen.tsx | 30 - packages/ui/src/icons/CheckboxIcon.tsx | 52 - packages/ui/src/icons/Checkmark.tsx | 4 +- .../ui/src/icons/CheckmarkCircleGreen.tsx | 4 +- .../ui/src/icons/CheckmarkCircleTier1.tsx | 4 +- .../ui/src/icons/CheckmarkCircleTier2.tsx | 4 +- .../ui/src/icons/CheckmarkCircleTier3.tsx | 4 +- packages/ui/src/icons/Chevron.tsx | 37 +- packages/ui/src/icons/ChevronLeft.tsx | 19 + packages/ui/src/icons/CircleCheck.tsx | 2 - packages/ui/src/icons/CircleCheckOutline.tsx | 2 - packages/ui/src/icons/CirclePlus.tsx | 2 - packages/ui/src/icons/Clock.tsx | 1 - packages/ui/src/icons/Close.tsx | 6 +- packages/ui/src/icons/Code.tsx | 6 +- packages/ui/src/icons/Copy.tsx | 6 +- packages/ui/src/icons/CreditCard.tsx | 44 +- packages/ui/src/icons/DeleteIcon.tsx | 4 +- packages/ui/src/icons/Dollar.tsx | 4 +- packages/ui/src/icons/DollarManrope.tsx | 20 + packages/ui/src/icons/DollarManropeSmall.tsx | 20 + .../ui/src/icons/DotGrid1x3Horizontal.tsx | 54 +- packages/ui/src/icons/Dots.tsx | 15 - packages/ui/src/icons/Down.tsx | 19 - packages/ui/src/icons/Download.tsx | 46 +- packages/ui/src/icons/Envelope.tsx | 20 + packages/ui/src/icons/ExclamationPoint.tsx | 62 +- packages/ui/src/icons/Exit.tsx | 20 - packages/ui/src/icons/Explorer.tsx | 30 +- packages/ui/src/icons/Eye.tsx | 42 +- packages/ui/src/icons/EyeDropper.tsx | 36 +- packages/ui/src/icons/Figma.tsx | 20 + packages/ui/src/icons/FlutterTwoTone.tsx | 10 +- packages/ui/src/icons/FramedLetterI.tsx | 44 +- packages/ui/src/icons/Gear.tsx | 4 +- packages/ui/src/icons/Github.tsx | 4 +- packages/ui/src/icons/GoTwoTone.tsx | 4 +- packages/ui/src/icons/GraphQLTwoTone.tsx | 4 +- packages/ui/src/icons/HeartOutline.tsx | 33 +- packages/ui/src/icons/Home.tsx | 2 - packages/ui/src/icons/HorizontalArrows.tsx | 6 +- packages/ui/src/icons/Info.tsx | 64 +- packages/ui/src/icons/InvoiceNew.tsx | 20 - packages/ui/src/icons/JavaScriptTwoTone.tsx | 10 +- packages/ui/src/icons/JavaTwoTone.tsx | 4 +- packages/ui/src/icons/KotlinTwoTone.tsx | 16 +- packages/ui/src/icons/LeftArrow.tsx | 36 +- .../ui/src/icons/LightningOnRoundedSquare.tsx | 32 +- packages/ui/src/icons/LinkIcon.tsx | 58 +- packages/ui/src/icons/LoadingSpinner.tsx | 13 +- packages/ui/src/icons/Lock.tsx | 4 +- packages/ui/src/icons/Logo.tsx | 4 +- packages/ui/src/icons/LogoBolt.tsx | 132 +- packages/ui/src/icons/LogoOnCircle.tsx | 54 +- packages/ui/src/icons/MagicWand.tsx | 72 +- packages/ui/src/icons/Mail.tsx | 21 - packages/ui/src/icons/Minus.tsx | 19 + packages/ui/src/icons/Monitor.tsx | 4 +- packages/ui/src/icons/NodeAdd.tsx | 32 +- packages/ui/src/icons/NotEye.tsx | 46 +- packages/ui/src/icons/NoteLine.tsx | 16 - packages/ui/src/icons/PaperPlane.tsx | 34 +- packages/ui/src/icons/Pencil.tsx | 39 +- packages/ui/src/icons/Person.tsx | 6 +- packages/ui/src/icons/PersonCircle.tsx | 25 + packages/ui/src/icons/Phone.tsx | 26 - packages/ui/src/icons/PiggyBank.tsx | 2 - packages/ui/src/icons/Plus.tsx | 70 +- packages/ui/src/icons/PythonTwoTone.tsx | 4 +- packages/ui/src/icons/QRCodeIcon.tsx | 11 +- packages/ui/src/icons/QuestionCircle.tsx | 20 + .../ui/src/icons/QuestionCircleStrong.tsx | 20 + packages/ui/src/icons/ReactTwoTone.tsx | 10 +- packages/ui/src/icons/Receive.tsx | 23 - packages/ui/src/icons/Recycling.tsx | 36 +- packages/ui/src/icons/Remove.tsx | 19 + packages/ui/src/icons/Restart.tsx | 35 +- packages/ui/src/icons/RightArrow.tsx | 36 +- packages/ui/src/icons/Roadmap.tsx | 36 +- packages/ui/src/icons/Route.tsx | 30 - packages/ui/src/icons/RustTwoTone.tsx | 4 +- packages/ui/src/icons/Satoshi.tsx | 4 +- packages/ui/src/icons/SatoshiRounded.tsx | 4 +- packages/ui/src/icons/Search.tsx | 38 +- packages/ui/src/icons/SecurityKey.tsx | 4 +- packages/ui/src/icons/Selector.tsx | 4 +- packages/ui/src/icons/SemiCircleOverlap.tsx | 4 +- packages/ui/src/icons/Send.tsx | 23 - packages/ui/src/icons/Share.tsx | 18 + packages/ui/src/icons/ShieldCheck.tsx | 19 + packages/ui/src/icons/Sidebar.tsx | 6 +- packages/ui/src/icons/Sort.tsx | 4 +- packages/ui/src/icons/StackedLines.tsx | 2 - packages/ui/src/icons/SwiftTwoTone.tsx | 4 +- packages/ui/src/icons/TapSingle.tsx | 18 + packages/ui/src/icons/Team.tsx | 36 +- packages/ui/src/icons/Terminal.tsx | 4 +- packages/ui/src/icons/Trash.tsx | 38 +- packages/ui/src/icons/TrashOld.tsx | 26 - packages/ui/src/icons/TwoArrowsDown.tsx | 2 - packages/ui/src/icons/TwoArrowsUp.tsx | 2 - packages/ui/src/icons/Uma.tsx | 8 +- packages/ui/src/icons/UmaBridgeLoading.tsx | 18 + packages/ui/src/icons/Upload.tsx | 46 +- packages/ui/src/icons/VerticalArrows.tsx | 32 - packages/ui/src/icons/ViewAll.tsx | 20 - packages/ui/src/icons/WalletSDKIcon.tsx | 4 +- packages/ui/src/icons/WarningIcon.tsx | 22 - packages/ui/src/icons/WarningSign.tsx | 56 +- packages/ui/src/icons/constants.tsx | 2 + packages/ui/src/icons/index.tsx | 112 +- packages/ui/src/modules.d.ts | 4 + packages/ui/src/styles/buttons.tsx | 85 + packages/ui/src/styles/colors.tsx | 317 +- packages/ui/src/styles/common.tsx | 21 +- packages/ui/src/styles/constants.ts | 5 + packages/ui/src/styles/fields.tsx | 28 +- .../ui/src/styles/fonts/typography/Body.tsx | 34 - .../styles/fonts/typography/BodyStrong.tsx | 38 - .../ui/src/styles/fonts/typography/Code.tsx | 21 - .../src/styles/fonts/typography/Display.tsx | 42 - .../ui/src/styles/fonts/typography/Label.tsx | 29 - .../styles/fonts/typography/LabelModerate.tsx | 44 - .../styles/fonts/typography/LabelStrong.tsx | 42 - .../src/styles/fonts/typography/Overline.tsx | 33 - .../ui/src/styles/fonts/typography/Title.tsx | 35 - .../ui/src/styles/fonts/typography/index.ts | 11 - .../ui/src/styles/fonts/typographyTokens.ts | 943 ----- packages/ui/src/styles/global.tsx | 9 +- packages/ui/src/styles/themes.tsx | 444 +++ packages/ui/src/styles/tokens/typography.ts | 3444 +++++++++++++++++ packages/ui/src/styles/type.tsx | 2 +- packages/ui/src/styles/typography.tsx | 31 + packages/ui/src/types/index.ts | 14 + packages/ui/src/utils/NextLink.tsx | 50 + packages/ui/src/utils/countryCodesToNames.tsx | 264 ++ .../ui/src/utils/isReactNodeWithChildren.tsx | 18 + packages/ui/src/utils/strings.tsx | 50 +- .../ui/src/utils/tests/toReactNodes.test.tsx | 156 - .../src/utils/toNonTypographicReactNodes.tsx | 160 + packages/ui/src/utils/toReactNodes.tsx | 170 +- packages/ui/src/utils/transformGQLName.tsx | 66 + packages/ui/src/utils/unicode.tsx | 1 + packages/ui/tsup.config.ts | 2 +- packages/vite/index.cjs | 5 + packages/vite/package.json | 2 +- packages/wallet-cli/package.json | 2 +- start.sh | 1 + turbo.json | 7 +- yarn.lock | 3279 ++++++++++++++-- 314 files changed, 16455 insertions(+), 5501 deletions(-) create mode 100644 .changeset/warm-vans-change.md create mode 100644 .changeset/wild-beans-suffer.md create mode 100644 .changeset/wise-tables-knock.md delete mode 100644 apps/examples/streaming-wallet-extension/src/components/CirclePlusIcon.tsx delete mode 100644 apps/examples/streaming-wallet-extension/src/components/LeftArrow.tsx create mode 100644 apps/examples/ui-test-app/.eslintrc.js create mode 100644 apps/examples/ui-test-app/.prettierignore create mode 100644 apps/examples/ui-test-app/.prettierrc create mode 100644 apps/examples/ui-test-app/gql-codegen.yml create mode 100644 apps/examples/ui-test-app/index.html rename {packages/ui => apps/examples/ui-test-app}/jest.config.ts (81%) create mode 100644 apps/examples/ui-test-app/jest/setup.ts create mode 100644 apps/examples/ui-test-app/jest/setupAfterEnv.ts create mode 100644 apps/examples/ui-test-app/package.json create mode 100644 apps/examples/ui-test-app/public/favicon-16.ico create mode 100644 apps/examples/ui-test-app/public/favicon-32.ico create mode 100644 apps/examples/ui-test-app/public/logo192.png create mode 100644 apps/examples/ui-test-app/public/logo512.png create mode 100644 apps/examples/ui-test-app/public/manifest.json create mode 100644 apps/examples/ui-test-app/public/robots.txt create mode 100644 apps/examples/ui-test-app/src/Root.tsx create mode 100644 apps/examples/ui-test-app/src/index.tsx create mode 100644 apps/examples/ui-test-app/src/tests/Banner.test.tsx create mode 100644 apps/examples/ui-test-app/src/tests/CodeInput.test.tsx create mode 100644 apps/examples/ui-test-app/src/tests/CommaNumberInput.test.tsx create mode 100644 apps/examples/ui-test-app/src/tests/TextIconAligner.test.tsx create mode 100644 apps/examples/ui-test-app/src/tests/Toasts.test.tsx create mode 100644 apps/examples/ui-test-app/src/tests/renderTypography.test.tsx create mode 100644 apps/examples/ui-test-app/src/tests/toReactNodes.test.tsx create mode 100644 apps/examples/ui-test-app/src/types.ts rename {packages/ui => apps/examples/ui-test-app}/tsconfig-test.json (85%) create mode 100644 apps/examples/ui-test-app/tsconfig.json create mode 100644 apps/examples/ui-test-app/vite.config.ts create mode 100644 apps/examples/uma-vasp/src/currencies.ts delete mode 100644 apps/examples/uma-vasp/src/rawLnurl.ts delete mode 100644 packages/react-native/examples/ReactNativeWallet/components/CurrencyAmount.tsx delete mode 100644 packages/react-native/examples/ReactNativeWallet/utils/currency.ts create mode 100644 packages/static/images/lightspark-logo.svg create mode 100644 packages/static/package.json create mode 100644 packages/ui/esbuild-svgr-plugin.ts create mode 100644 packages/ui/src/components/Banner/Banner.tsx create mode 100644 packages/ui/src/components/Banner/constants.ts create mode 100644 packages/ui/src/components/Checkbox.tsx create mode 100644 packages/ui/src/components/CodeInput/CodeInput.tsx create mode 100644 packages/ui/src/components/CodeInput/SingleCodeInput.tsx create mode 100644 packages/ui/src/components/CommaNumberInput.tsx create mode 100644 packages/ui/src/components/Drawer.tsx create mode 100644 packages/ui/src/components/Dropdown.tsx delete mode 100644 packages/ui/src/components/Icon.tsx create mode 100644 packages/ui/src/components/Icon/Icon.tsx create mode 100644 packages/ui/src/components/Icon/types.tsx create mode 100644 packages/ui/src/components/InfoIconTooltip.tsx create mode 100644 packages/ui/src/components/PageSection/PageSection.tsx create mode 100644 packages/ui/src/components/PageSection/PageSectionNav.tsx create mode 100644 packages/ui/src/components/PageSection/constants.tsx create mode 100644 packages/ui/src/components/PhoneInput.tsx create mode 100644 packages/ui/src/components/Radio.tsx create mode 100644 packages/ui/src/components/TextButton.tsx create mode 100644 packages/ui/src/components/TextInput.tsx create mode 100644 packages/ui/src/components/Toasts.tsx create mode 100644 packages/ui/src/components/Toggle.tsx rename packages/ui/src/components/{LightTooltip.tsx => Tooltip.tsx} (77%) create mode 100644 packages/ui/src/components/documentation/DocsBodyParagraph.tsx create mode 100644 packages/ui/src/components/documentation/DocsBodyStrongParagraph.tsx rename packages/ui/src/{styles/fonts/typography/Headline.tsx => components/documentation/DocsHeadline.tsx} (52%) create mode 100644 packages/ui/src/components/documentation/Video.tsx rename packages/ui/src/{styles/fonts => components}/typography/Article.tsx (60%) create mode 100644 packages/ui/src/components/typography/Body.tsx create mode 100644 packages/ui/src/components/typography/BodyStrong.tsx create mode 100644 packages/ui/src/components/typography/Code.tsx create mode 100644 packages/ui/src/components/typography/Display.tsx create mode 100644 packages/ui/src/components/typography/Headline.tsx create mode 100644 packages/ui/src/components/typography/Label.tsx create mode 100644 packages/ui/src/components/typography/LabelModerate.tsx create mode 100644 packages/ui/src/components/typography/LabelStrong.tsx create mode 100644 packages/ui/src/components/typography/Overline.tsx create mode 100644 packages/ui/src/components/typography/Title.tsx create mode 100644 packages/ui/src/components/typography/index.tsx create mode 100644 packages/ui/src/components/typography/renderTypography.tsx create mode 100644 packages/ui/src/hooks/useDebounce.tsx create mode 100644 packages/ui/src/hooks/useResizeObserver.tsx create mode 100644 packages/ui/src/icons/ArrowCircle.tsx create mode 100644 packages/ui/src/icons/ArrowUpRightCircleFill.tsx create mode 100644 packages/ui/src/icons/Bank.tsx delete mode 100644 packages/ui/src/icons/Bell.tsx delete mode 100644 packages/ui/src/icons/BellOn.tsx delete mode 100644 packages/ui/src/icons/Bolt.tsx delete mode 100644 packages/ui/src/icons/Camera.tsx create mode 100644 packages/ui/src/icons/CaretRight.tsx delete mode 100644 packages/ui/src/icons/Channel.tsx delete mode 100644 packages/ui/src/icons/ChannelBalance.tsx delete mode 100644 packages/ui/src/icons/ChannelOpen.tsx delete mode 100644 packages/ui/src/icons/CheckboxIcon.tsx create mode 100644 packages/ui/src/icons/ChevronLeft.tsx create mode 100644 packages/ui/src/icons/DollarManrope.tsx create mode 100644 packages/ui/src/icons/DollarManropeSmall.tsx delete mode 100644 packages/ui/src/icons/Dots.tsx delete mode 100644 packages/ui/src/icons/Down.tsx create mode 100644 packages/ui/src/icons/Envelope.tsx delete mode 100644 packages/ui/src/icons/Exit.tsx create mode 100644 packages/ui/src/icons/Figma.tsx delete mode 100644 packages/ui/src/icons/InvoiceNew.tsx delete mode 100644 packages/ui/src/icons/Mail.tsx create mode 100644 packages/ui/src/icons/Minus.tsx delete mode 100644 packages/ui/src/icons/NoteLine.tsx create mode 100644 packages/ui/src/icons/PersonCircle.tsx delete mode 100644 packages/ui/src/icons/Phone.tsx create mode 100644 packages/ui/src/icons/QuestionCircle.tsx create mode 100644 packages/ui/src/icons/QuestionCircleStrong.tsx delete mode 100644 packages/ui/src/icons/Receive.tsx create mode 100644 packages/ui/src/icons/Remove.tsx delete mode 100644 packages/ui/src/icons/Route.tsx delete mode 100644 packages/ui/src/icons/Send.tsx create mode 100644 packages/ui/src/icons/Share.tsx create mode 100644 packages/ui/src/icons/ShieldCheck.tsx create mode 100644 packages/ui/src/icons/TapSingle.tsx delete mode 100644 packages/ui/src/icons/TrashOld.tsx create mode 100644 packages/ui/src/icons/UmaBridgeLoading.tsx delete mode 100644 packages/ui/src/icons/VerticalArrows.tsx delete mode 100644 packages/ui/src/icons/ViewAll.tsx delete mode 100644 packages/ui/src/icons/WarningIcon.tsx create mode 100644 packages/ui/src/icons/constants.tsx create mode 100644 packages/ui/src/styles/buttons.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/Body.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/BodyStrong.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/Code.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/Display.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/Label.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/LabelModerate.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/LabelStrong.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/Overline.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/Title.tsx delete mode 100644 packages/ui/src/styles/fonts/typography/index.ts delete mode 100644 packages/ui/src/styles/fonts/typographyTokens.ts create mode 100644 packages/ui/src/styles/themes.tsx create mode 100644 packages/ui/src/styles/tokens/typography.ts create mode 100644 packages/ui/src/styles/typography.tsx create mode 100644 packages/ui/src/utils/NextLink.tsx create mode 100644 packages/ui/src/utils/countryCodesToNames.tsx create mode 100644 packages/ui/src/utils/isReactNodeWithChildren.tsx delete mode 100644 packages/ui/src/utils/tests/toReactNodes.test.tsx create mode 100644 packages/ui/src/utils/toNonTypographicReactNodes.tsx create mode 100644 packages/ui/src/utils/transformGQLName.tsx create mode 100644 packages/ui/src/utils/unicode.tsx diff --git a/.changeset/warm-vans-change.md b/.changeset/warm-vans-change.md new file mode 100644 index 000000000..b04ac868a --- /dev/null +++ b/.changeset/warm-vans-change.md @@ -0,0 +1,23 @@ +--- +"@lightsparkdev/ui": patch +--- + +- Remove unused icons (#10179) +- Preload icons (#10182) +- Fix invalid color string (#10231) +- Add ChevronLeft icon (#10198) +- Add InfoIconTooltip component and improve Tooltip (#10236) +- Add Radio component (#10350) +- Typography and theme improvements (#10331) +- Add Banner component (#10262) +- Consolidate specifying full precision for currencies (#1095) +- Add NextLink as a ToReactNode type (#10432) +- Button improvements (#10507) +- Update to latest typography tokens (#10536) +- Add transformGQLName (#10592) +- ToReactNodes improvements and tests (#10562) +- Add icons (#10572) +- Provide icon color inversion when color is specified (#10630) +- Add PhoneInput component (#10702) +- Add useDebounce hook (#10741) +- Add common Drawer component, optionally use in Modal (#10819) diff --git a/.changeset/wild-beans-suffer.md b/.changeset/wild-beans-suffer.md new file mode 100644 index 000000000..40736792e --- /dev/null +++ b/.changeset/wild-beans-suffer.md @@ -0,0 +1,6 @@ +--- +"@lightsparkdev/core": minor +--- + +- Move formatCurrencyStr options into an object (#1095) +- Compress requests with deflate (#10512) diff --git a/.changeset/wise-tables-knock.md b/.changeset/wise-tables-knock.md new file mode 100644 index 000000000..c72505673 --- /dev/null +++ b/.changeset/wise-tables-knock.md @@ -0,0 +1,12 @@ +--- +"@lightsparkdev/ui": major +--- + +- Move PageSectionNav to new UI component (#9971) +- Move all PageSection components and Dropdown to public UI (#9979) +- Allow Modal submit to be a link (#10066) +- Move themes to own file. Simplify colors (#10167) +- Move typography and tokens (#10172) +- Improve theme typography tokens and add bridge tokens (#10189) +- Move typography to components (#10178) +- Update dependencies diff --git a/apps/examples/oauth-app/package.json b/apps/examples/oauth-app/package.json index 547591c57..6921f4b68 100644 --- a/apps/examples/oauth-app/package.json +++ b/apps/examples/oauth-app/package.json @@ -27,7 +27,7 @@ "eslint-watch": "^8.0.0", "tsc-absolute": "^1.0.1", "typescript": "^5.0.0", - "vite": "^5.0.5" + "vite": "^5.1.6" }, "scripts": { "start": "yarn vite", diff --git a/apps/examples/oauth-app/src/index.tsx b/apps/examples/oauth-app/src/index.tsx index 7675e17cc..165ae6832 100644 --- a/apps/examples/oauth-app/src/index.tsx +++ b/apps/examples/oauth-app/src/index.tsx @@ -7,7 +7,7 @@ import "./index.css"; import reportWebVitals from "./reportWebVitals"; import { Root } from "./Root"; import { ThemeProvider } from "@emotion/react"; -import { themes } from "@lightsparkdev/ui/styles/colors"; +import { themes } from "@lightsparkdev/ui/styles/themes"; const root = ReactDOM.createRoot( document.getElementById("root") as HTMLElement diff --git a/apps/examples/oauth-app/src/pages/DashboardPage.tsx b/apps/examples/oauth-app/src/pages/DashboardPage.tsx index 0e15dde7d..2eac6aec0 100644 --- a/apps/examples/oauth-app/src/pages/DashboardPage.tsx +++ b/apps/examples/oauth-app/src/pages/DashboardPage.tsx @@ -46,7 +46,7 @@ function DashboardPage() {
); }; @@ -145,7 +145,7 @@ const InitializeWallet = ({ return (

Wallet not yet initialized. Status: {status}

-
); }; diff --git a/apps/examples/react-wallet-app/src/pages/LoginPage.tsx b/apps/examples/react-wallet-app/src/pages/LoginPage.tsx index a026fe55f..f01472ebf 100644 --- a/apps/examples/react-wallet-app/src/pages/LoginPage.tsx +++ b/apps/examples/react-wallet-app/src/pages/LoginPage.tsx @@ -30,14 +30,19 @@ const LoginPage = () => { const generateDemoTokens = async () => { const { token: jwt, accountId: jwtServerAccountId } = await fetch( - `${jwtServerUrl.replace(/\/$/, "")}/getJwt?userId=${userName}&password=${password}`, + `${jwtServerUrl.replace( + /\/$/, + "" + )}/getJwt?userId=${userName}&password=${password}`, { method: "GET", headers: { "ngrok-skip-browser-warning": "true", - } + }, } - ).then((res) => res.json() as Promise<{ token: string, accountId: string }>); + ).then( + (res) => res.json() as Promise<{ token: string; accountId: string }> + ); await auth.login(jwtServerAccountId, jwt); navigate(Routes.Dashboard); }; @@ -62,7 +67,7 @@ const LoginPage = () => { onChange={(e) => setJwt(e.target.value)} /> - Transactions @@ -341,7 +340,7 @@ function LoginScreen(props: { {!isLoading ? ( - + ) : ( <> diff --git a/apps/examples/streaming-wallet-extension/src/components/CirclePlusIcon.tsx b/apps/examples/streaming-wallet-extension/src/components/CirclePlusIcon.tsx deleted file mode 100644 index b4914d6de..000000000 --- a/apps/examples/streaming-wallet-extension/src/components/CirclePlusIcon.tsx +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright ©, 2022, Lightspark Group, Inc. - All Rights Reserved - -const CirclePlusIcon = () => ( - - - -); - -export default CirclePlusIcon; diff --git a/apps/examples/streaming-wallet-extension/src/components/LeftArrow.tsx b/apps/examples/streaming-wallet-extension/src/components/LeftArrow.tsx deleted file mode 100644 index c07251cb0..000000000 --- a/apps/examples/streaming-wallet-extension/src/components/LeftArrow.tsx +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright ©, 2022, Lightspark Group, Inc. - All Rights Reserved - -const LeftArrow = () => ( - - - -); - -export default LeftArrow; diff --git a/apps/examples/ui-test-app/.eslintrc.js b/apps/examples/ui-test-app/.eslintrc.js new file mode 100644 index 000000000..c0a94025e --- /dev/null +++ b/apps/examples/ui-test-app/.eslintrc.js @@ -0,0 +1,23 @@ +module.exports = { + extends: ["@lightsparkdev/eslint-config/react-lib"], + /* Mainly keeping this file around for reference for future public react lib, ignore in lint: */ + ignorePatterns: ["src/generated/"], + overrides: [ + { + files: ["**/src/**/*.ts?(x)"], + excludedFiles: ["**/tests/**/*.ts?(x)"], + rules: { + /* Temporarily turn off no-explicit-any until these can be resolved LIG-3400: */ + "@typescript-eslint/no-explicit-any": "off", + /* Too many of these type-aware errors, turn off for now: */ + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-misused-promises": "off", + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/no-unsafe-return": "off", + }, + }, + ], +}; diff --git a/apps/examples/ui-test-app/.prettierignore b/apps/examples/ui-test-app/.prettierignore new file mode 100644 index 000000000..d3db8f9b1 --- /dev/null +++ b/apps/examples/ui-test-app/.prettierignore @@ -0,0 +1 @@ +src/generated/ diff --git a/apps/examples/ui-test-app/.prettierrc b/apps/examples/ui-test-app/.prettierrc new file mode 100644 index 000000000..55c1943ae --- /dev/null +++ b/apps/examples/ui-test-app/.prettierrc @@ -0,0 +1,3 @@ +{ + "plugins": ["prettier-plugin-organize-imports"] +} diff --git a/apps/examples/ui-test-app/gql-codegen.yml b/apps/examples/ui-test-app/gql-codegen.yml new file mode 100644 index 000000000..14875df40 --- /dev/null +++ b/apps/examples/ui-test-app/gql-codegen.yml @@ -0,0 +1,11 @@ +overwrite: true +schema: ["../../../../sparkcore/graphql_schemas/first_party_schema.graphql"] +documents: ["src/**/*.tsx"] +generates: + src/generated/graphql.tsx: + plugins: + - "typescript" + - "typescript-operations" + - "typescript-react-apollo" + config: + nonOptionalTypename: true diff --git a/apps/examples/ui-test-app/index.html b/apps/examples/ui-test-app/index.html new file mode 100644 index 000000000..297ea69dd --- /dev/null +++ b/apps/examples/ui-test-app/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + Lightspark + + + + + + + + +
+ + + + diff --git a/packages/ui/jest.config.ts b/apps/examples/ui-test-app/jest.config.ts similarity index 81% rename from packages/ui/jest.config.ts rename to apps/examples/ui-test-app/jest.config.ts index a4915e613..d2cf931c9 100644 --- a/packages/ui/jest.config.ts +++ b/apps/examples/ui-test-app/jest.config.ts @@ -19,9 +19,6 @@ const config: JestConfigWithTsJest = { testTimeout: 20000, moduleNameMapper: { "^.+\\.(css|svg|png)$": "identity-obj-proxy", - /* ts-jest doesn't support .js imports which are required for making imports work in - the published ui package. See issue https://bit.ly/3TF1uSS */ - "(.+)\\.js": "$1", }, setupFiles: ["/jest/setup.ts"], setupFilesAfterEnv: ["/jest/setupAfterEnv.ts"], diff --git a/apps/examples/ui-test-app/jest/setup.ts b/apps/examples/ui-test-app/jest/setup.ts new file mode 100644 index 000000000..1f5fb2185 --- /dev/null +++ b/apps/examples/ui-test-app/jest/setup.ts @@ -0,0 +1,23 @@ +/* Import node libs to polyfill browser objects */ +import crypto from "crypto"; +import ResizeObserver from "resize-observer-polyfill"; + +import { TextDecoder, TextEncoder } from "util"; + +Object.defineProperties(global.self, { + crypto: { + value: { + getRandomValues: (arr: NodeJS.ArrayBufferView) => + crypto.randomFillSync(arr), + subtle: crypto.webcrypto.subtle, + }, + }, + TextEncoder: { + value: TextEncoder, + }, + TextDecoder: { + value: TextDecoder, + }, +}); + +global.ResizeObserver = ResizeObserver; diff --git a/apps/examples/ui-test-app/jest/setupAfterEnv.ts b/apps/examples/ui-test-app/jest/setupAfterEnv.ts new file mode 100644 index 000000000..d0de870dc --- /dev/null +++ b/apps/examples/ui-test-app/jest/setupAfterEnv.ts @@ -0,0 +1 @@ +import "@testing-library/jest-dom"; diff --git a/apps/examples/ui-test-app/package.json b/apps/examples/ui-test-app/package.json new file mode 100644 index 000000000..ef4866c9a --- /dev/null +++ b/apps/examples/ui-test-app/package.json @@ -0,0 +1,98 @@ +{ + "name": "@lightsparkdev/ui-test-app", + "version": "0.0.0", + "description": "Lightspark UI components", + "author": "Lightspark Inc.", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "sideEffects": false, + "scripts": { + "build": "yarn tsc && yarn vite build", + "circular-deps": "madge --circular --extensions ts,tsx src", + "clean": "rm -rf .turbo && rm -rf dist", + "dev": "yarn build --watch", + "format:fix": "prettier src --write", + "format": "prettier src --check", + "lint:fix": "eslint --fix .", + "lint:watch": "esw ./src -w --ext .ts,.tsx,.js --color", + "lint": "eslint .", + "postversion": "yarn build", + "start": "yarn vite", + "preview": "yarn tsc && yarn vite preview", + "test": "node --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --bail", + "types": "echo \"TODO: Some imports depend on the inheriting app config. May not be possible to run types here separately unless we fix that.\"", + "types:watch": "echo \"TODO: Some imports depend on the inheriting app config. May not be possible to run types here separately unless we fix that.\"" + }, + "license": "Apache-2.0", + "dependencies": { + "@apollo/client": "^3.9.11", + "@emotion/css": "^11.11.0", + "@emotion/react": "^11.11.0", + "@emotion/styled": "^11.11.0", + "@lightsparkdev/core": "1.0.22", + "@lightsparkdev/ui": "0.0.13", + "@wojtekmaj/react-datetimerange-picker": "^5.5.0", + "@zxing/browser": "^0.1.1", + "@zxing/library": "^0.19.2", + "auto-bind": "^5.0.1", + "chart.js": "4.2.0", + "dayjs": "^1.11.7", + "deep-object-diff": "^1.1.9", + "nanoid": "^4.0.0", + "qrcode.react": "^3.1.0", + "react": "^18.2.0", + "react-date-picker": "^10.6.0", + "react-datetime-picker": "^5.6.0", + "react-device-detect": "^2.2.3", + "react-dom": "^18.1.0", + "react-router-dom": "6.11.2", + "react-table": "^7.8.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@babel/core": "^7.21.4", + "@emotion/babel-plugin": "^11.11.0", + "@graphql-codegen/cli": "^5.0.2", + "@graphql-codegen/typescript": "^4.0.6", + "@graphql-codegen/typescript-operations": "^4.2.0", + "@graphql-codegen/typescript-react-apollo": "^4.3.0", + "@lightsparkdev/eslint-config": "*", + "@lightsparkdev/tsconfig": "*", + "@lightsparkdev/vite": "*", + "@simbathesailor/use-what-changed": "^2.0.0", + "@testing-library/jest-dom": "^6.1.2", + "@types/jest": "^29.5.3", + "@vitejs/plugin-react": "^4.0.1", + "babel-jest": "^29.6.4", + "eslint": "^8.3.0", + "eslint-watch": "^8.0.0", + "graphql": "^16.6.0", + "graphql-tag": "^2.12.6", + "identity-obj-proxy": "^3.0.0", + "jest": "^29.6.2", + "jest-environment-jsdom": "^29.6.4", + "madge": "^6.1.0", + "prettier": "3.0.3", + "prettier-plugin-organize-imports": "^3.2.4", + "resize-observer-polyfill": "^1.5.1", + "ts-jest": "^29.1.1", + "tsc-absolute": "^1.0.1", + "tsup": "^7.2.0", + "typescript": "^5.0.0", + "vite": "^5.1.6" + }, + "madge": { + "detectiveOptions": { + "ts": { + "skipTypeImports": true + }, + "tsx": { + "skipTypeImports": true + } + } + }, + "engines": { + "node": ">=18" + } +} diff --git a/apps/examples/ui-test-app/public/favicon-16.ico b/apps/examples/ui-test-app/public/favicon-16.ico new file mode 100644 index 0000000000000000000000000000000000000000..a87e750eedc03686997d1bfd4a1488f2af396ffc GIT binary patch literal 4286 zcmeH}!EuBz3`La=IOWVSM@pasN}vPi06KsU;FvBb0Xm=rN+5ooQHEh*lf{gES?vge zSm&cP5;pXh`5;MiijvbV6FtnpudRC_$* zib1(h;Jgn!M}D?1+@(+S4woyv<}Q6Imn_R3>KpyB=4XyJF;{&)<8rhvM{}+<8KT$h zwWB)Ue+z)kmES(r*|lPrrs?-vK=-AyXYQU?eX7pEg!#&W^4aQhyD#Z|AEWA%UKk<= za8!MwclxCd-uoD;&rmr4k7~oU-|e}*at#Lh@hi{V{a^HXWzV`B$NPQqpE@vU3THo? C1o(ge literal 0 HcmV?d00001 diff --git a/apps/examples/ui-test-app/public/favicon-32.ico b/apps/examples/ui-test-app/public/favicon-32.ico new file mode 100644 index 0000000000000000000000000000000000000000..edecb5b07789f3b43a97e86fb595a14c272be600 GIT binary patch literal 16958 zcmeHM(UF2M5Y2Vq*M0MOpO(N}1$Lk%*nxDQ9cTyIfhA}MmS71SkDKT0>;RWZIDssC z69SQN?Aw=po58t{>Mze-b$%Ms%p90G5X^zi zW)nO&h5Q5m4~K(k3?7e1c{-iS#bRL+huv;h!tVEbnPr(d4B#^jT(F1%_)mL2pXGA7 zG{pnS0pI`(tZ9Sf0J%^Ug&7`b4iE!N`gpxwYq!CFo@2m@KIVB|`;P<8_xt_p+KN6x z17V0iYFyR_7_*>{$on+b0_*jfL$x-fu8-uv@pydYf2;@O1z76(*u(*>1@M8`0Ed+I zk$y@J5Ch~wTB`ae^B(g6_x#u^rml~&9%|!x>iW1^t?GRMavx)_d&v{58O;@ae~Q=E z^sy<1mh`d7e~gVy9}$zjTbu732L@6f+j1xG|IZ%lk~JIkI=1i1h4f`i`iNScwM?w< zn18ukTD5@wvmc8->UD{l4r8H>{`vG{(MNDnuFH4Utx_Ms#i90(zyPtQp@zknPaI?K z8IwN7a1wrCe;CrB1=5DphENRTJn2j5`H&b$eS}W>Xd81W)^T4An8vQJ(D_;)x7+Pt z?-J@m>^#Pl93GOBvA%@P2L?mwW9U2gJ#R>T?Aw=^=gAz890zVRJr6Y$YKZgs-1vLb zoT-fYU;w?K`Dn*feCK=m=p*<60}nVarC#eJ>OSdT+qVLF&(zQV(noSYe=C@}-}3#t z^w9zbfJK)+THpZrAhiKC6SyJA+Vqn1Q|P6?h`rQ8EA_M1$J^~zYa#GRA;vyFXnm{! zs18~ueV#Sdd$c|R14|r0+_XLd14|qL23jAjae(VrYD0?qBKq0Y6N6OuMP0u0H|nE> qdWb&j9{TvsZ%z9DkKx*K{KtU*{0`1cJwC^Jj}R4&eD6@ee$pw}A! literal 0 HcmV?d00001 diff --git a/apps/examples/ui-test-app/public/logo192.png b/apps/examples/ui-test-app/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..c31b513a7e9656d95e1aaec976df335fa4a0cac2 GIT binary patch literal 2211 zcmb_eeK?bQAD<{CnuENY~ZKY%; zy`0iYiO5w>nrU*ghm)dGr<<}9cV1>M&rj#Np8ucgdj7b7_xJ7h{e185_4|B(cTr4q zxRu5C78nf1DuNtF1@A{Q&)hj+rS_$pV=!~~M1+O@lx_0)Lf(NcvR&BIuGt}T`6g#_ z56xLROOSWL#M&eU6EyCMn^ko)~2~- z$osb6M#jh0v=^dxwcZ~?Z|-CcJ+yU2;~y9a}s;pgRzT;qsAH}wv`c~5fE;)H|* z3Zy!Rml;jLzS*wpkE|*{zYZr~2Qc!Sn>Oh`MCauspc8$%WNu$A2?-%vpo z{o)kOVv~*DQY9(3PL}E&jNh#BwFO!7XEg57OQ^x$gKod+1e0B`#(4o%hXrfv6!_Z0QW zsuuAZZN47otht2-6$xp!PlAa3jYo$mCAx{pmRej5Y9FRZ9|Kmy5#yJ`Bt)}OYhL32 zl28Mw+S}XZ8c+R??)2ISQ0(I+L7m(HDnsI#Rh2r_NR%2GQe{v}rz~|+FXh?*`LS4* zO8%HH!Zw6?(rf3b!3TbbzA*VHl0ap=r@cfizZ@ohi&WgMM4UW@2K+-GlH$78Hc6R# zIhu-O_<^{dKhe{n+GQIR*X?lPGIuFAQ>s+(FC$LJP|6u0Z5}m{xIqUyM;Hgmq8s8a zNX75i>$`YqHc63wSGtc~Fqs#j7k2>s&6xmy3%jjA*gMqv0<}y+e3nxg*E|y7fa9p@ zq_B4nXlQM`K+4UMD(zDvV8L4xyML4=EI43XQ)0-OQk8p8RbB6Y{rb#$y8fpojy}`D z!C}N;c%AX9@!tBQT7ou^8-Tw?$)fmF7x^@wm4zcmLwUm9SH0JeykxTI)vpi5F5Unv zv8Nu%yG$0fKYtBj?ZOr5@ui>8>xp}Fhxq;yE3u0lxMo2-rc}AKQ1)~kl_3a)O|fJV zGz-G6OWx;j;ae8X>b=5OwLH9bDaV*RzJr0dDPaIa~Hgzu? zaBsBlY~zus+r!3}G@K1@$AxpDU!rs(dumHQE*@He_w8^*i>Z2{d{ka@@R@l6J=i zd{@zYd3UL7nQOtZN{)a)%<*%Ix$&A`uzwd*|)VT?(M+k z|H>ZvYW{N9+@5Ll&ZUR&MT_3NC|d~!t)j?0q{qUxk}$-ZHwCK#X&v*RCo@ zc^ULH_Eo@}e^I5u5akeAcOKaTgk5%~wD?ODcnv+TOVc;@Qne$c*F+BsxtnLx}0qM{TOT(S|+Ni72qV9>~Gg7i%GV2Qt^I1uy@HUlPW?V~nf8e1HyNVg}s zW;@w_O9`E6$}V0AQ3QZx(Mo@b14IEVgcN;>F{Byn1oaAR1fUJ=p7bCmKagzqES&t= zxk#?q1(XVrya7;p(rCmNaFJASpU0{*HZ!)yuKdbeA$E~8{QSqkRnFU4mx8C|_4R96 z9L{T_S;)9oV9hqCnNoA4%6-ZAM?YO0zcT20+l`)O%R@AhvbMHJoQ7|OlV8h;;%2c2 zgz`dT+KyLwnh}j=S}Zt~h$FN%A%Dk;71(ME=6d4HFNh*&Ji->?-GAeZ+KYS_qs?i=9?bB(qkKZH|#-b zGFxQ#FUwiE?Ax3KtI%cFFFdz8cCy#HF$I~^Xr&GXP9%jmh-*@<4I{TFo* zGJaH9`Mte^13823z@3uUp_mu_WwhA^@4wDV7-UTw!}O6X+W*filbjn)>=$DZ5g$h} z=c6EB(oHcoQpfQ0_FkCeX{(`_RY!!RKaJS9LgqFdmT?K2@%nypZ3W7q8zZzv)j`V8 zq?1ADPICo9^vMTIaw`uT>R*Mdd>ENx>`EIWY^xmF-x`)o9JME#8kAAY&(TqNBt45r zPXE*S6gf(;h#592qrcu!O1}XbjMO zb+Ix-L#t5jjUz&aJ@GhdE^^SI$Z*-p(o1RCBJ#UgBH$8`R=dI^XJ%%6-0aD+X9}ox zML3WSlkzmdmKI05mLzo_05T3^KsB7rwzRTQkdd|U$@G`3Dthbeb!e^K?l&mvqV^0#bF5RhPBBG|?PyGjc;Q z!Q(Twq@5WodSy|S^LZgQR>CKy`yAQ=QOu`jT+A~&F_Lt8R9(G3$JY#kS{#?ef53A7i&h-@Qc^g-tr`5bwME;A1-8Wjcl4~@~C2zJd(!m7W zt?&&dXlPPE*Pp)q!pC0@nHbP<59y>5pofD>ZSFV4wD?#eVp8e#I@x6z9WQ`FJ#l~8 zWprVv48mb3m!S&|v~qIKq#Wk2axO=IK1qXz-3ZoXI-Ndwveeys z+PmW${!1FRcuzZkUAU>E#iN@J2+U_};?0{k+TJq@lYMoQQpsrFhY!cL2t*tWZuh-? zEWTMBhD*=5)JZ#^4wS6pNs_XNj-T>Xbn>UJUAyMmTf_FS(~C|R7#JWIt7wd9&(!ZK z))?VUx#~6#4=@$ahKH9IY%JD)=5l$0ADq=`6Z~Umg`Ok+_RD!f_^DI(3O4RstWO)Z z3AX6xGa6ewyB|2mr?wve&kl5{mE8VN{UotMnR_XXbuUR(+rIzdWnACDfaAF<>Tp`W zxa6fZ@JTSK2OF5x_Fzy$`XM zPRYbT7LkifgHXg1_!~G8)wOxrhc#uysR-#^t)!&XLJaqh|C$SlMyd5rlgG+T$q64J z=4o+?P5-xb3RzgxzrW%UFuG}K5Usg5%#-wDi~^2$26BrIg#MM zvP|l~$weO|RlYOGBv0iIuc;RAl{$b20}@xSUhP^@QBkPc&sFF5)SUP%qy^k})N>VH z^MxF%&BMN|R{KIy8WtPaxr5l<_u+De^i*qAg~Pd!f>!a(_;OCE)m`eIOl);F6F5o0 zx(!qm7&wOs$)TaV=OBD#>VE6El1rD*Toy@{L2h}?-3s2V(?v9Zxd zdn!^(po8_Dqbx@p90F~<=5<^sFX8(?Gf6FsG1c24RNcJp{S-tN^2j;!hvH$nDW(6r@X*lv1wL0G|2j9cVbzx_ zQyIqjQxw8|O*?6#4%?2h@l^BngTgW=t}Xhv&jO}8sNYC>2w^) z)prMvnw2c3`hl3af{J!A~bacO|KlD0S$a# z#d(d7dXwkx{;z>|jY93|=ygQTSBMNhdD76+(^H|ozP_&g)2C0DA)V;=*U_E}l+oN1 zY4*&?urTAh6TV7Lk85f)I%gM`8m*jiZ~6DXM9pEu;-eR_Lh>-txET%B8 zuAw2Fl+W;yvr2;wX`nvQMPC4U(y?YpUN_bQov!CHVsy~yzqyRs-az#6G82m-L%)vE zzbTfV^DaiE5p-OJXjl;=FcK+Eh6T%%?t_i&;Z-R9sF3y^D!=X(KxwXAUV8*kUS;VZ z-Ctp2{1v*M0l)7+LU+Ij2Mn!r07z6sA_|b>fw)J6v>XLDw6BiKurl9lG5Jn?S5PS{*Mne(iaqeP|&5WO9`K6ztv<5SCHM*1)2{hd2Ek@hdk&RJh*DxU;BI+re! zqnb>Nhe~;QbCK&xy2E{gy^7KPOH4A{9Cvc^{5^gF&wjF%VT^2F8sl%EGt%n~X`G)7 zxu}Sep;7!&r{kH}?3#*!NV5GqFxB-Fbe{S)WcxQ4TY!RG5cu+ACeSP53X2SMN>~Sa zAA1!sY8~-FckSqC!(55WBWG;$`4<&vOTiGA9~(QinYapVE>QnGuYv^aS>i;SD?A=g z?s0qrriStk3mNimXvQ@WY=uU1o8a;{w@X9GkvA0~ zh53S#Q&CY_BmV!>{Eph28Ez?54Gs?0!2Ysj&~QjY9SXOyvhK1@GJol=F^lV}G8!&_ z+YdBciaRy;w20HnONN3TwY9Z5Gt`2d3j_s@r{WCsB^}?S=^t`TDIfj#@lJQpqsrws zMgD&#KAs_IIa67m%r);h-;WkI6h7ncP)d&Lw^BK!F1g8mwc7N zuZ%OsV9i;7o!*o2i+*ni+2egzaD2mo?=XjS3wo;oQf1!6O$TptN#PZ+SN((~) z-SR)^&HD=kta^YN_Y-;>Lk{jX0*-Hh<5l2T{vWwap%4@*8Ux2$Ow5!*x%eLxML;>f z@r#gdM*$_f;fs(RP&^AaQ(Pz%sEDi-U_TC3`mqsD59GwJQ)>`sFnWHLzad?sDez%$ zqIISX#O7OCSSXx5dseRT^QU(^u$Pyf^)^a^9`$t;y4AH8mz2axEXjI4ue1o7E&NcC z%@y(g`0X&l)sH`d%2wPIz=>Ad=gVeJovKjM6lf*kMInur*^6D7F^~WS^kUhk#cyTz z{V}AuM;Zz#dTCT$$UozuuP@=V7sBVJ2OH7C$>kd^nAzPm_{Y`UrIkaCqhtPTkKm=m zu9Eo>ZaRZl^LcQU)d0)Ok;||r7Z&EG22MsrS=j2WFd6tTQO9wNRzL3Q>3DkD-`bvh z9B+d|59P9R@#w$n8aP_q^aEpB$%L&Qy~7y4bsRq3fA&MF$AlbJTVjG9+$czWq}uY{ zP}GtVh*XaVIqvc~xmo|&@R3QH>tVtt%f`etyJ885>F_aw`@|0K5h_a^@ zC`LbB%sUIi*gJD`^K%yS4tO7pheuQ8^5+LdI~}HpM+|J;y>f*1Rd|g;9VwOS*iDm4_{U3JyakA@y0d4Y!Box)w<|x zkpngVQ6$FYa`JI`!JD{0xg&c@O4iqZDy-dlIe0A1E zC=ESV&`VY(Cnvio-h1*}!oTx42_{rmn4AAWgs~eeIwsg}U%!4`aJj^rzcaYn2oL10 zgWIaLXKJJKwBy;%HRDg7{Pa&kYZ&wy>^Yk^OKqEVcEo^lrf8Pa`WIt{`AQ-x~t>{Jp*^l~L>#7)?6qEM6#L|XZSZG0vc@C(J$)3SQHi_0&2 zPW6!m!ji?Hsf#VJezmmDT@olBrlVXxcd4is4(6zXyd-G(RerMJZ-)f9mZGye*MZby zugnmqRcQelYM4`yr~8^b$R(RPmA?6?%`{2T}b(0u1mt`E`)+t8@YUwTDnd z!uuLnA{uNS(0SuDrSTbWs#PsdX(I&!LBR^()dsvwJZ#MH`pI|jvbMBGHMb@nuPHlf zCV=e%ZX7vKoMNsY4^|NGrnoy=+~uWo8{p6m^*%LL{2|B_=yt?^^*M=^O`Nco*1KFb zC$oMC>MD_&y!+>$f8I`!{591_5Ycz~`umT-Yu)-h6+Wk~uCDLXr(hJyeBkjrD{U&3 z5B-$l0y6+4&SzRks;;O>(ejcyoxeB@ zouBXz%2djN{;gtwJwNUHYVTcN{I*5)c?s)gw?rZtc(bUX zp|K)|whbAkum?k;az4$x=#^N``LL%A$~T^SNwwwM8CD#jXYuvCEgEee!kx4KKu{M@ zLzY129EZ(Wibm&05C&H|U+7@e;kyvI(}C;}4eLi$Ro&7a5?&i%25|CyH30^Xz@-m; z81EUvF;{L0ObBV{?Ku4 zPj^MeQpjNE&ZYMc8|0@0i|)dVl0{SCN6oX{h3-7kJ(-v~0oSYSD7a|cv#1R#Vv+|g zf(IhO)xwt@X4E}Sp#%tLjkJMkKmAj&YUk$YTXT~8i({Im9$=UqF4JO$MkVwaS^+>N z=n(aU@_p69l<+YSqMDn4QERUZaw?YrL9R)Sc10N@OAEampj^(n;zq#TE4xmKMGfR; zalo}K=gV?Q8WAwc>C_1B6?UUTid^0U0w0uvsiMptAs{=wZE-IPIq4xk(ihm zt56d)Z?t}Cs`B%ZtNjDwX5`eG)+%_su*hB<=wZ~ZZ$hP8PEGJ7iZM(qXSpA|WmbxN zr(@x6Gyh6%8@IA5n<2qc}R7%yTsm=si9F!F#2Zc38C-=EYLzG_L=>p0c=-F1#XhfBAy@qJ>OF%#~faDj|$1f z#VGVX#19>}Z=f<#4DU5+O)ul%d4I>_W`?-G79Ol@B+WKmuVY*9uTrK6Bx7`4HkGKa$-XH(l_FO`vBMdQ+T zbkx@|2L-#Za(ohuSjvF0^WpeW4CE4vPou+(U>U>AAgWN%a&&jaH2JkH@t6i;Dw#{f zZ0i)zgI6CYEth&d89J!l5fmzgBv==X+Njym>qoeA@;9?}khA11#n#FaV#WoY#2knP z7`R7Z0%pP6-enjVF^hR>v}XIEJ3~-`$T>T_PdLJKK$$d0hiRcumAu6 literal 0 HcmV?d00001 diff --git a/apps/examples/ui-test-app/public/manifest.json b/apps/examples/ui-test-app/public/manifest.json new file mode 100644 index 000000000..a931ae928 --- /dev/null +++ b/apps/examples/ui-test-app/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "Lightspark", + "name": "Lightspark App", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/apps/examples/ui-test-app/public/robots.txt b/apps/examples/ui-test-app/public/robots.txt new file mode 100644 index 000000000..e9e57dc4d --- /dev/null +++ b/apps/examples/ui-test-app/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/apps/examples/ui-test-app/src/Root.tsx b/apps/examples/ui-test-app/src/Root.tsx new file mode 100644 index 000000000..81e22ada9 --- /dev/null +++ b/apps/examples/ui-test-app/src/Root.tsx @@ -0,0 +1,79 @@ +import { ThemeProvider } from "@emotion/react"; +import styled from "@emotion/styled"; +import { + Button, + Checkbox, + Modal, + TextInput, + Toggle, +} from "@lightsparkdev/ui/components"; +import { Headline } from "@lightsparkdev/ui/components/typography"; +import { GlobalStyles } from "@lightsparkdev/ui/styles/global"; +import { themes } from "@lightsparkdev/ui/styles/themes"; +import { useState } from "react"; + +export function Root() { + const [showModal, setShowModal] = useState(false); + const [submitting, setSubmitting] = useState(false); + const [textInputValue, setTextInputValue] = useState(""); + const [checkboxValue, setCheckboxValue] = useState(true); + const [toggleValue, setToggleValue] = useState(true); + return ( + + + + UI Test App + + + - void; + grabber?: boolean; + closeButton?: boolean; +} + +export const Drawer = (props: Props) => { + const [isOpen, setIsOpen] = useState(true); + const [lastY, setLastY] = useState(null); + const [totalDeltaY, setTotalDeltaY] = useState(0); + const [fractionVisible, setFractionVisible] = useState(1); + const [grabbing, setGrabbing] = useState(false); + const drawerContainerRef = useRef(null); + + const handleClose = () => { + setIsOpen(false); + + setTimeout(() => { + props.onClose && props.onClose(); + setTotalDeltaY(0); + setLastY(null); + }, 300); + }; + + const handleTouchMove = (event: React.TouchEvent) => { + if (lastY === null) { + setLastY(event.touches[0].clientY); + } else { + const deltaY = event.touches[0].clientY - lastY; + + const topOfDrawer = + (drawerContainerRef.current?.getBoundingClientRect().top || 0) + + window.scrollY; + const drawerContainerHeight = + drawerContainerRef.current?.getBoundingClientRect().height || 1; + const newFractionVisible = Math.min( + 1, + (window.innerHeight - topOfDrawer) / drawerContainerHeight, + ); + setFractionVisible(newFractionVisible); + setLastY(event.touches[0].clientY); + setTotalDeltaY((prev) => Math.max(prev + deltaY, 0)); + } + }; + + const handleTouchStart = () => { + setGrabbing(true); + }; + + const handleTouchEnd = () => { + setGrabbing(false); + if (fractionVisible < 0.8) { + handleClose(); + } + setTotalDeltaY(0); + setLastY(null); + }; + + return ( + <> + + + {props.grabber && ( + + + + )} + {props.closeButton && ( + + + + )} + {props.children} + + + ); +}; + +const Background = styled.div<{ isOpen: boolean; fractionVisible: number }>` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: ${z.modalOverlay}; + + // Animate opacity + transition: opacity 0.3s ease-in-out; + opacity: ${(props) => (props.isOpen ? props.fractionVisible : "0")}; + + animation: open 0.3s ease-in-out; + + @keyframes open { + from { + opacity: 0; + } + to { + opacity: 1; + } + } +`; + +const DrawerContainer = styled.div<{ + isOpen: boolean; + totalDeltaY: number; + grabbing: boolean; +}>` + position: absolute; + width: 100%; + background-color: ${({ theme }) => theme.bg}; + right: 0; + bottom: 0; + transform: translateY(${(props) => `${props.totalDeltaY}px`}); + z-index: ${z.modalContainer}; + border-radius: ${Spacing.lg} ${Spacing.lg} 0 0; + display: flex; + flex-direction: column; + padding: ${Spacing["6xl"]} ${Spacing.xl} ${Spacing["2xl"]} ${Spacing.xl}; + + // Only smooth transition when not grabbing, otherwise dragging will feel very laggy + ${(props) => + props.grabbing && props.isOpen + ? "" + : "transition: transform 0.3s ease-in-out;"}; + + // Animate the drawer opening and closing, and make sure the the drawer stays closed. + animation: 0.3s ease-in-out + ${(props) => (props.isOpen ? "openDrawer" : "closeDrawer forwards")}; + + @keyframes openDrawer { + from { + transform: translateY(100%); + } + to { + transform: translateY(0%); + } + } + + @keyframes closeDrawer { + from { + transform: translateY(${(props) => `${props.totalDeltaY}px`}); + } + to { + transform: translateY(100%); + } + } +`; + +const Grabber = styled.div` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: ${Spacing.lg}; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 9px; + cursor: pointer; +`; + +const CloseButtonContainer = styled.div` + position: absolute; + top: 20px; + right: 20px; + border-radius: 50%; + background-color: ${colors.grayBlue94}; + padding: ${Spacing.xs}; + + * > * { + line-height: 14px; + } +`; + +const GrabberBar = styled.div` + width: 36px; + height: 5px; + border-radius: 2.5px; + background: #c0c9d6; +`; diff --git a/packages/ui/src/components/Dropdown.tsx b/packages/ui/src/components/Dropdown.tsx new file mode 100644 index 000000000..1d11c835f --- /dev/null +++ b/packages/ui/src/components/Dropdown.tsx @@ -0,0 +1,498 @@ +import type { CSSInterpolation } from "@emotion/css"; +import { css, useTheme } from "@emotion/react"; +import type { CSSObject } from "@emotion/styled"; +import styled from "@emotion/styled"; +import type { ReactNode, RefObject } from "react"; +import { + useCallback, + useEffect, + useLayoutEffect, + useRef, + useState, +} from "react"; +import ReactDOM from "react-dom"; +import { + Link, + type ExternalLink, + type LinkProps, + type RouteHash, + type RouteParams, +} from "../router.js"; +import { bp } from "../styles/breakpoints.js"; +import { + overlaySurface, + standardBorderRadius, + standardFocusOutline, +} from "../styles/common.js"; +import { smHeaderLogoMarginLeft } from "../styles/constants.js"; +import { themeOr, type ThemeProp, type WithTheme } from "../styles/themes.js"; +import { z } from "../styles/z-index.js"; +import { Icon } from "./Icon/Icon.js"; +import { type IconName } from "./Icon/types.js"; +import { UnstyledButton } from "./UnstyledButton.js"; + +type DropdownItemGetProps = WithTheme<{ + dropdownItem: DropdownItemType; +}>; + +type DropdownItemType = { + label: string; + getIcon?: + | (({ theme, dropdownItem }: DropdownItemGetProps) => + | { + name: IconName; + color?: string; + width?: number; + } + | undefined) + | undefined; + onClick?: ((dropdownItem: DropdownItemType) => void) | undefined; + getCSS?: ({ + dropdownItem, + theme, + }: DropdownItemGetProps) => CSSInterpolation; + to?: RoutesType | undefined; + externalLink?: ExternalLink | undefined; + params?: RouteParams | undefined; + selected?: boolean; + hash?: RouteHash; +}; + +type DropdownGetProps = WithTheme<{ isOpen: boolean }>; + +type DropdownProps = { + button: { + label?: string; + id?: string; + getContent?: ({ isOpen, theme }: DropdownGetProps) => ReactNode; + getCSS?: ({ isOpen, theme }: DropdownGetProps) => CSSInterpolation; + }; + dropdownItems?: DropdownItemType[]; + dropdownContent?: ReactNode; + openOnHover?: boolean; + horizontalScrollRef?: RefObject; + minDropdownItemsWidth?: number; + maxDropdownItemsWidth?: number; + onClickDropdownItems?: () => void; + closeOnScroll?: boolean; + align?: "left" | "right" | "center"; + footer?: ReactNode | null; + getCSS?: ({ isOpen, theme }: DropdownGetProps) => CSSObject; + onOpen?: () => void; + onClose?: () => void; +}; + +export function Dropdown({ + button, + dropdownItems, + horizontalScrollRef, + onClickDropdownItems, + getCSS, + onOpen, + onClose, + closeOnScroll = false, + openOnHover = false, + minDropdownItemsWidth = 200, + maxDropdownItemsWidth = 300, + align = "center" as const, + footer = null, + dropdownContent = null, +}: DropdownProps) { + const theme = useTheme(); + const [isOpen, setIsOpen] = useState(false); + const [dropdownButtonHeight, setDropdownButtonHeight] = useState(0); + const [dropdownButtonWidth, setDropdownButtonWidth] = useState(0); + const [dropdownCoords, setDropdownCoords] = useState({ + top: 0, + left: 0, + right: 0, + }); + const dropdownRef = useRef(null); + const dropdownButtonRef = useRef(null); + const dropdownItemsRef = useRef(null); + const [dropdownItemsWidth, setDropdownItemsWidth] = useState(0); + const nodeRef = useRef(null); + const [nodeReady, setNodeReady] = useState(false); + + useEffect(() => { + if (!nodeRef.current) { + nodeRef.current = document.createElement("div"); + document.body.appendChild(nodeRef.current); + } + setNodeReady(true); + return () => { + if (nodeRef.current) { + document.body.removeChild(nodeRef.current); + nodeRef.current = null; + } + }; + }, []); + + const setOpen = useCallback( + (newValue: boolean) => { + setIsOpen(newValue); + if (newValue && onOpen) { + onOpen(); + } else if (!newValue && onClose) { + onClose(); + } + }, + [onOpen, onClose], + ); + + function handleKeyDown(event: React.KeyboardEvent) { + if (event.key === "Escape") { + event.preventDefault(); + setOpen(false); + } else if (["Enter", "Return"].includes(event.key)) { + event.preventDefault(); + setOpen(!isOpen); + } + } + + function handleBlur( + event: React.FocusEvent, + ) { + const targetOutsideDropdownItems = + dropdownItemsRef.current && + !dropdownItemsRef.current.contains(event.relatedTarget) && + event.relatedTarget !== null; + if (targetOutsideDropdownItems) { + setOpen(false); + } + } + + const handleRef = useCallback((ref: HTMLButtonElement | null) => { + if (ref && !dropdownButtonRef.current) { + dropdownButtonRef.current = ref; + } + return ref; + }, []); + + // close dropdown when clicking outside of it + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + const targetOutsideDropdownItems = + dropdownItemsRef.current && + !dropdownItemsRef.current.contains(event.target as Node); + const targetOutsideDropdownButton = + dropdownButtonRef.current && + !dropdownButtonRef.current.contains(event.target as Node); + if ( + isOpen && + event.target && + targetOutsideDropdownItems && + targetOutsideDropdownButton + ) { + setOpen(false); + } + } + window.document.addEventListener("mousedown", handleClickOutside); + return () => { + window.document.removeEventListener("mousedown", handleClickOutside); + }; + }, [isOpen, setOpen]); + + const reposition = useCallback(() => { + if (dropdownButtonRef.current && dropdownItemsRef.current) { + const dropdownButtonRect = + dropdownButtonRef.current.getBoundingClientRect(); + setDropdownCoords({ + top: dropdownButtonRect.top, + left: dropdownButtonRect.left, + right: dropdownButtonRect.right, + }); + setDropdownButtonHeight(dropdownButtonRect.height); + setDropdownButtonWidth(dropdownButtonRect.width); + + const dropdownItemsRect = + dropdownItemsRef.current.getBoundingClientRect(); + setDropdownItemsWidth(dropdownItemsRect.width); + } + }, []); + + // handle all cases where a dropdown nav needs to be repositioned: + useLayoutEffect(() => { + function onWindowResize() { + setOpen(false); + reposition(); + } + + function handleScroll() { + if (closeOnScroll) { + setOpen(false); + } + reposition(); + } + + reposition(); + + let dropdownButtonResizeObserver: ResizeObserver | null = null; + if (dropdownButtonRef.current) { + dropdownButtonResizeObserver = new ResizeObserver(reposition); + dropdownButtonResizeObserver.observe(dropdownButtonRef.current); + } + + let dropdownResizeObserver: ResizeObserver | null = null; + if (dropdownButtonRef.current) { + dropdownResizeObserver = new ResizeObserver(reposition); + dropdownResizeObserver.observe(dropdownButtonRef.current); + } + + window.addEventListener("resize", onWindowResize); + + let navItemsResizeObserver: ResizeObserver | null = null; + window.addEventListener("scroll", handleScroll); + if (horizontalScrollRef?.current) { + horizontalScrollRef.current.addEventListener("scroll", handleScroll); + navItemsResizeObserver = new ResizeObserver(reposition); + navItemsResizeObserver.observe(horizontalScrollRef.current); + } + return () => { + window.removeEventListener("resize", onWindowResize); + window.removeEventListener("scroll", handleScroll); + dropdownButtonResizeObserver?.disconnect(); + navItemsResizeObserver?.disconnect(); + dropdownResizeObserver?.disconnect(); + }; + }, [setOpen, horizontalScrollRef, closeOnScroll, reposition]); + + const handleClickDropdownItems = useCallback(() => { + setOpen(false); + onClickDropdownItems && onClickDropdownItems(); + }, [onClickDropdownItems, setOpen]); + + const dropdownTopMargin = 8; + const dropdownItemOffsetTop = + dropdownCoords.top + dropdownButtonHeight + dropdownTopMargin; + + let dropdownItemOffsetLeft = 0; + + if (align === "center") { + dropdownItemOffsetLeft = + dropdownCoords.left - (dropdownItemsWidth - dropdownButtonWidth) / 2; + } else if (align === "right") { + dropdownItemOffsetLeft = dropdownCoords.right - dropdownItemsWidth; + } + + const buttonContent = + button.label || (button.getContent && button.getContent({ isOpen, theme })); + + const containerCSS = getCSS && getCSS({ isOpen, theme }); + + return ( +
+ { + reposition(); + setOpen(true); + } + : undefined + } + onMouseLeave={ + openOnHover + ? () => { + setOpen(false); + } + : undefined + } + onMouseDown={(e) => { + reposition(); + setOpen(!isOpen); + }} + onKeyDown={handleKeyDown} + onFocus={(e) => { + reposition(); + setOpen(true); + }} + onBlur={handleBlur} + ref={handleRef} + css={button.getCSS && button.getCSS({ isOpen, theme })} + > + {buttonContent} + + {nodeReady && nodeRef.current + ? ReactDOM.createPortal( + + {dropdownItems?.map((dropdownItem, i) => { + return ( +
  • + +
  • + ); + })} + {dropdownContent} + {footer && {footer}} +
    , + nodeRef.current, + ) + : null} +
    + ); +} + +const DropdownFooter = styled.div` + padding: 24px 16px 0; + border-top: 1px solid ${({ theme }) => theme.c2Neutral}; + margin-top: 16px; +`; + +type DropdownItemsProps = { + isOpen: boolean; + left: number; + top: number; + minWidth?: number; + maxWidth?: number; +}; + +const DropdownItems = styled.ul` + ${overlaySurface} + color: ${({ theme }) => themeOr(theme.c6Neutral, theme.c8Neutral)}; + ${standardBorderRadius(8)} + padding: 12px 0; + visibility: ${({ isOpen }) => (isOpen ? "visible" : "hidden")}; + position: fixed; + ${({ minWidth }) => (minWidth ? `min-width: ${minWidth}px;` : "")} + ${({ maxWidth }) => (maxWidth ? `max-width: ${maxWidth}px;` : "")} + left: ${({ left }) => left}px; + top: ${({ top }) => top}px; + z-index: ${z.dropdown}; + list-style: none; + margin: 0; +`; + +type DropdownItemProps = { + dropdownItem: DropdownItemType & { selected?: boolean }; + onClick?: () => void; + getCSS?: ({ + dropdownItem, + theme, + }: DropdownItemGetProps) => CSSInterpolation; +}; + +function DropdownItem({ + dropdownItem, + onClick, +}: DropdownItemProps) { + const theme = useTheme(); + + const dropdownItemIcon = + dropdownItem.getIcon && dropdownItem.getIcon({ dropdownItem, theme }); + const dropdownItemIconNode = dropdownItemIcon ? ( + + ) : null; + + const cssProp = + dropdownItem.getCSS && dropdownItem.getCSS({ theme, dropdownItem }); + + const onClickDropdownItem = useCallback(() => { + dropdownItem.onClick && dropdownItem.onClick(dropdownItem); + onClick && onClick(); + }, [dropdownItem, onClick]); + + // to may be '' for the current route so check !== undefined + if (dropdownItem.to !== undefined || dropdownItem.externalLink) { + // single nav item + + return ( + + selected={Boolean(dropdownItem.selected)} + to={dropdownItem.to} + externalLink={dropdownItem.externalLink} + params={dropdownItem.params} + onClick={onClickDropdownItem} + css={cssProp} + hash={dropdownItem.hash} + > + {dropdownItemIconNode} + {dropdownItem.label} + + ); + } + + return ( + + {dropdownItemIconNode} + {dropdownItem.label} + + ); +} + +const DropdownButton = styled(UnstyledButton)` + ${standardFocusOutline} +`; + +type DropdownItemStyleProps = WithTheme<{ selected?: boolean }>; + +const dropdownItemStyle = ({ selected, theme }: DropdownItemStyleProps) => ` + background-color: ${selected ? theme.primary : "transparent"}; + box-sizing: border-box; + cursor: pointer; + display: flex; + flex-direction: row; + align-items: center; + height: 100%; + outline-color: ${selected ? theme.onPrimaryText : theme.hcNeutral} !important; + white-space: nowrap; + + padding: 8px 16px; + ${bp.sm(`padding-left: ${smHeaderLogoMarginLeft};`)} + + &:hover { + color: ${theme.hcNeutral} !important; + } +`; + +type StyledDropdownItemProps = { + selected?: boolean; +}; + +const cssProp = ({ + theme, + selected, +}: ThemeProp & StyledDropdownItemProps) => css` + ${dropdownItemStyle({ theme, selected: Boolean(selected) })} + ${standardFocusOutline({ theme })} +`; + +function DropdownItemLink( + props: StyledDropdownItemProps & LinkProps, +) { + const theme = useTheme(); + return ( + + {...props} + css={cssProp({ theme, selected: Boolean(props.selected) })} + /> + ); +} + +const DropdownItemDiv = styled.div` + ${dropdownItemStyle} + ${standardFocusOutline} +`; diff --git a/packages/ui/src/components/FileInput.tsx b/packages/ui/src/components/FileInput.tsx index 53a889578..a3e9abc34 100644 --- a/packages/ui/src/components/FileInput.tsx +++ b/packages/ui/src/components/FileInput.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; import { Fragment, useRef, useState } from "react"; import { InputSubtext, inputBlockStyle } from "../styles/fields.js"; -import { Icon } from "./Icon.js"; +import { Icon } from "./Icon/Icon.js"; import { Pill } from "./Pill.js"; type FileInputProps = { diff --git a/packages/ui/src/components/Icon.tsx b/packages/ui/src/components/Icon.tsx deleted file mode 100644 index 7cb949cc0..000000000 --- a/packages/ui/src/components/Icon.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import styled from "@emotion/styled"; -import { useLayoutEffect, useState } from "react"; -import { rootFontSizePx } from "../styles/common.js"; -import { isString } from "../utils/strings.js"; - -type Component = () => JSX.Element; - -type IconMap = { - [key: string]: Component; -}; - -const iconMap: IconMap = {}; - -async function loadIcon(iconName: string) { - let IconComp: Component; - try { - ({ default: IconComp } = (await import( - /* webpackMode: "eager" */ - // this can't be a variable only, needs to have some string constraints: - `./icons/${iconName}.js` - )) as { default: Component }); - } catch (e) { - throw new Error(`Icon ${iconName} not found`); - } - iconMap[iconName] = IconComp; -} - -type IconProps = { - className?: string; - name: string; - width: number; - mr?: number; - ml?: number; - verticalAlign?: "middle" | "top" | "bottom" | "super" | number; - color?: string | undefined; - tutorialStep?: number; -}; - -export function Icon({ - className, - name, - width, - tutorialStep, - mr = 0, - ml = 0, - verticalAlign = "middle", - color = undefined, -}: IconProps) { - const [, setLoading] = useState(false); - - const IconComponent = iconMap[name] || null; - - useLayoutEffect(() => { - void (async () => { - if (!iconMap[name]) { - setLoading(true); - await loadIcon(name); - setLoading(false); - } - })(); - }, [name]); - - // Assume width is px relative to the root font size but specify in ems to - // preserve scale for larger font sizes - const w = parseFloat((width / rootFontSizePx).toFixed(2)); - const mrRems = parseFloat((mr / rootFontSizePx).toFixed(2)); - const mlRems = parseFloat((ml / rootFontSizePx).toFixed(2)); - const va = - typeof verticalAlign === "string" - ? verticalAlign - : parseFloat((verticalAlign / rootFontSizePx).toFixed(2)); - - return ( - - {IconComponent ? : null} - - ); -} - -type IconContainerProps = { - w: number; - mr: number; - ml: number; - verticalAlign: string | number; - fontColor?: string | undefined; -}; - -export const IconContainer = styled.span` - pointer-events: none; - display: inline-flex; - ${({ mr, ml, w }) => ` - width: ${w}em; - /* ensure no shrink in flex containers: */ - min-width: ${w}em; - ${mr ? `margin-right: ${mr}em;` : ""} - ${ml ? `margin-left: ${ml}em;` : ""} - `} - - vertical-align: ${({ verticalAlign }) => - isString(verticalAlign) ? verticalAlign : `${verticalAlign}em`}; - - ${({ fontColor }) => ` - & svg { - color: ${fontColor || "inherit"}; - } - `} -`; diff --git a/packages/ui/src/components/Icon/Icon.tsx b/packages/ui/src/components/Icon/Icon.tsx new file mode 100644 index 000000000..72a31124a --- /dev/null +++ b/packages/ui/src/components/Icon/Icon.tsx @@ -0,0 +1,107 @@ +"use client"; + +import styled from "@emotion/styled"; +import { invertFillColor, invertStrokeColor } from "../../icons/constants.js"; +import * as icons from "../../icons/index.js"; +import { rootFontSizePx } from "../../styles/common.js"; +import { getFontColor, type FontColorKey } from "../../styles/themes.js"; +import { isString } from "../../utils/strings.js"; +import type { IconName } from "./types.js"; + +type IconProps = { + className?: string | undefined; + name: IconName; + width: number; + mr?: number | undefined; + ml?: number | undefined; + verticalAlign?: "middle" | "top" | "bottom" | "super" | number; + color?: FontColorKey | undefined; + tutorialStep?: number; +}; + +export function Icon({ + className, + name, + width, + tutorialStep, + mr = 0, + ml = 0, + color = undefined, + verticalAlign = "middle", +}: IconProps) { + const IconComponent = icons[name] || null; + + /** Assume width is px relative to the root font size but specify + * in ems to preserve scale for larger font sizes */ + const w = parseFloat((width / rootFontSizePx).toFixed(2)); + const mrRems = parseFloat((mr / rootFontSizePx).toFixed(2)); + const mlRems = parseFloat((ml / rootFontSizePx).toFixed(2)); + const va = + typeof verticalAlign === "string" + ? verticalAlign + : parseFloat((verticalAlign / rootFontSizePx).toFixed(2)); + + return ( + + {IconComponent ? : null} + + ); +} + +type IconContainerProps = { + w: number; + mr: number; + ml: number; + verticalAlign: string | number; + fontColor?: FontColorKey | undefined; +}; + +export const IconContainer = styled.span` + pointer-events: none; + display: inline-flex; + ${({ mr, ml, w }) => ` + width: ${w}em; + /* ensure no shrink in flex containers: */ + min-width: ${w}em; + ${mr ? `margin-right: ${mr}em;` : ""} + ${ml ? `margin-left: ${ml}em;` : ""} + `} + + vertical-align: ${({ verticalAlign }) => + isString(verticalAlign) ? verticalAlign : `${verticalAlign}em`}; + + ${({ theme, fontColor }) => { + const color = getFontColor(theme, fontColor, "inherit"); + return ` + & svg { + color: ${getFontColor(theme, fontColor, "inherit")}; + + /* + Provide a way for an SVG to invert relative to a specified color for + dark mode support. Ideally we would just use filters, which works in + Chrome even if the color is not specified, but doesn't work at all for + SVG paths in Safari: + filter: invert(100%); -webkit-filter: invert(100%); + + Instead we'll need a class for fills and a class for strokes. Icons + that need inverted colors should use these classes on their paths. + */ + + .${invertFillColor} { + fill: ${fontColor ? theme.hcNeutralFromBg(color) : "currentColor"}; + } + .${invertStrokeColor} { + stroke: ${fontColor ? theme.hcNeutralFromBg(color) : "currentColor"}; + } + } + `; + }} +`; diff --git a/packages/ui/src/components/Icon/types.tsx b/packages/ui/src/components/Icon/types.tsx new file mode 100644 index 000000000..a3e94fd9c --- /dev/null +++ b/packages/ui/src/components/Icon/types.tsx @@ -0,0 +1,3 @@ +import type * as icons from "../../icons/index.js"; + +export type IconName = keyof typeof icons; diff --git a/packages/ui/src/components/InfoIconTooltip.tsx b/packages/ui/src/components/InfoIconTooltip.tsx new file mode 100644 index 000000000..5ef37e620 --- /dev/null +++ b/packages/ui/src/components/InfoIconTooltip.tsx @@ -0,0 +1,30 @@ +import { Fragment } from "react"; +import { type TypographyTypeKey } from "../styles/tokens/typography.js"; +import { toReactNodes, type ToReactNodesArgs } from "../utils/toReactNodes.js"; +import { Icon } from "./Icon/Icon.js"; +import { Tooltip } from "./Tooltip.js"; + +type InfoIconTooltipProps = { + id: string; + content: ToReactNodesArgs; + verticalAlign?: "middle" | number; +}; + +export function InfoIconTooltip({ + id, + content, + verticalAlign = "middle", +}: InfoIconTooltipProps) { + const contentNodes = toReactNodes(content); + return ( + +
    + +
    + contentNodes} clickable /> +
    + ); +} diff --git a/packages/ui/src/components/LightsparkProvider.tsx b/packages/ui/src/components/LightsparkProvider.tsx index 2c306a10e..b885b25a8 100644 --- a/packages/ui/src/components/LightsparkProvider.tsx +++ b/packages/ui/src/components/LightsparkProvider.tsx @@ -1,6 +1,6 @@ import { ThemeProvider } from "@emotion/react"; -import { themes } from "../styles/colors.js"; import { GlobalStyles } from "../styles/global.js"; +import { themes } from "../styles/themes.js"; type LightsparkProviderProps = { children: React.ReactNode; diff --git a/packages/ui/src/components/Loading.tsx b/packages/ui/src/components/Loading.tsx index 80b916939..0522a53da 100644 --- a/packages/ui/src/components/Loading.tsx +++ b/packages/ui/src/components/Loading.tsx @@ -1,5 +1,6 @@ +import { useTheme } from "@emotion/react"; import styled from "@emotion/styled"; -import { Icon } from "./Icon.js"; +import { Icon } from "./Icon/Icon.js"; type Props = { center?: boolean; @@ -18,10 +19,11 @@ export function Loading({ size = defaultProps.size, ml = defaultProps.ml, }: Props) { + const theme = useTheme(); return ( - + ); diff --git a/packages/ui/src/components/Modal.tsx b/packages/ui/src/components/Modal.tsx index 0222eb7fb..4d5f40932 100644 --- a/packages/ui/src/components/Modal.tsx +++ b/packages/ui/src/components/Modal.tsx @@ -12,20 +12,46 @@ import { standardContentInset, standardFocusOutline, } from "../styles/common.js"; -import { overflowAutoWithoutScrollbars, pxToRems } from "../styles/utils.js"; +import { Spacing } from "../styles/tokens/spacing.js"; +import { TokenSize } from "../styles/tokens/typography.js"; +import { overflowAutoWithoutScrollbars } from "../styles/utils.js"; import { z } from "../styles/z-index.js"; import { select } from "../utils/emotion.js"; -import { toReactNodes } from "../utils/toReactNodes.js"; -import { Button } from "./Button.js"; -import { Icon } from "./Icon.js"; +import { toReactNodes, type ToReactNodesArgs } from "../utils/toReactNodes.js"; +import { Button, ButtonSelector } from "./Button.js"; +import { Drawer } from "./Drawer.js"; +import { Icon } from "./Icon/Icon.js"; import { ProgressBar, type ProgressBarProps } from "./ProgressBar.js"; import { UnstyledButton } from "./UnstyledButton.js"; +import { Body } from "./typography/Body.js"; +import { Headline, headlineSelector } from "./typography/Headline.js"; -type ModalProps = { +export interface ExtraAction { + /** Determines the placement relative to the submission/cancel buttons. */ + placement: "above" | "below"; + content: React.ReactNode; +} + +type SubmitLinkWithRoute = { + to: RoutesType; +}; + +type SubmitLinkWithHref = { + href: string; + filename?: string; +}; + +function isSubmitLinkWithHref( + submitLink: SubmitLinkWithRoute | SubmitLinkWithHref | undefined, +): submitLink is SubmitLinkWithHref { + return Boolean(submitLink && "href" in submitLink); +} + +type ModalProps = { visible: boolean; onClose: () => void; - title?: string; - description?: string | undefined; + title?: ToReactNodesArgs; + description?: ToReactNodesArgs; cancelText?: string | undefined; cancelDisabled?: boolean; cancelHidden?: boolean; @@ -35,6 +61,11 @@ type ModalProps = { submitDisabled?: boolean; submitLoading?: boolean; submitText?: string; + submitLink?: + | { + to: RoutesType; + } + | SubmitLinkWithHref; children?: React.ReactNode; /* most of the time this is an Element but not in the case of Select - it * just extends .focus method: */ @@ -42,12 +73,17 @@ type ModalProps = { /* This should always be true for accessibility purposes unless you are * managing focus in a child component */ autoFocus?: boolean; + smDrawer?: boolean; nonDismissable?: boolean; width?: 460 | 600; progressBar?: ProgressBarProps; + /** Determines if buttons are laid out horizontally or vertically */ + buttonLayout?: "horizontal" | "vertical"; + /** Allows placing extra buttons in the same button layout */ + extraActions?: ExtraAction[]; }; -export function Modal({ +export function Modal({ visible, title, description, @@ -61,13 +97,17 @@ export function Modal({ submitDisabled, submitLoading, submitText, + submitLink, cancelText = "Cancel", firstFocusRef, + smDrawer, nonDismissable = false, autoFocus = true, width = 460, progressBar, -}: ModalProps) { + buttonLayout = "horizontal", + extraActions, +}: ModalProps) { const visibleChangedRef = useRef(false); const nodeRef = useRef(null); const [defaultFirstFocusRef, defaultFirstFocusRefCb] = useLiveRef(); @@ -78,7 +118,6 @@ export function Modal({ const modalContainerRef = useRef(null); const bp = useBreakpoints(); const isSm = bp.current(Breakpoints.sm); - const formattedDescription = description ? toReactNodes(description) : null; useEffect(() => { if (visible !== visibleChangedRef.current) { @@ -160,8 +199,8 @@ export function Modal({ } }, [visible, visibleChanged, ref, autoFocus]); - function onClickCloseButton(event: React.MouseEvent) { - event.stopPropagation(); + function onClickCloseButton(event?: React.MouseEvent) { + event?.stopPropagation(); onClose(); } @@ -180,75 +219,134 @@ export function Modal({ } } + const linkIsHref = isSubmitLinkWithHref(submitLink); + const linkIsRoute = !linkIsHref && submitLink; + + const buttonContent = ( + <> + {extraActions + ?.filter((action) => action.placement === "above") + .map((action) => action.content)} + {!isSm && !cancelHidden && ( +