mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 20:52:14 +01:00
Compare commits
2 Commits
feature/vo
...
feature/bi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf78dbdc37 | ||
|
|
b22132b0f2 |
23
.github/VOUCHED.td
vendored
23
.github/VOUCHED.td
vendored
@@ -1,23 +0,0 @@
|
|||||||
# Vouched contributors for solidtime.
|
|
||||||
#
|
|
||||||
# One handle per line, without the leading @, sorted alphabetically.
|
|
||||||
# Prefix a handle with - to denounce them, optionally followed by a reason.
|
|
||||||
# Format reference: https://github.com/mitchellh/vouch
|
|
||||||
#
|
|
||||||
# Maintainers do not need to edit this file by hand. Comment "vouch @user",
|
|
||||||
# "unvouch @user" or "denounce @user <reason>" on any issue, pull request or
|
|
||||||
# discussion and the vouch workflows will update this file.
|
|
||||||
#
|
|
||||||
# Collaborators with write access and bots are always allowed and do not need
|
|
||||||
# an entry here.
|
|
||||||
#
|
|
||||||
# Seeded 2026-07-25 from the authors of every merged pull request.
|
|
||||||
|
|
||||||
agross
|
|
||||||
candideu
|
|
||||||
KasparRosin
|
|
||||||
korridor
|
|
||||||
Onatcer
|
|
||||||
ShrootBuck
|
|
||||||
smileBeda
|
|
||||||
utlark
|
|
||||||
75
.github/workflows/vouch-check-pr.yml
vendored
75
.github/workflows/vouch-check-pr.yml
vendored
@@ -1,75 +0,0 @@
|
|||||||
name: Vouch (check PR)
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, reopened, synchronize]
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 5
|
|
||||||
if: >-
|
|
||||||
github.event_name == 'pull_request_target' ||
|
|
||||||
(github.event_name == 'issue_comment' &&
|
|
||||||
github.event.issue.pull_request &&
|
|
||||||
contains(github.event.comment.body, '/recheck'))
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Pull requests of 50 changed lines or fewer skip the vouch requirement.
|
|
||||||
- name: "Measure diff size"
|
|
||||||
id: size
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
REPO: ${{ github.repository }}
|
|
||||||
PR: ${{ github.event.pull_request.number || github.event.issue.number }}
|
|
||||||
|
|
||||||
# Changes to these files do not count towards the 50-line limit.
|
|
||||||
# One extended regex per line, matched against the whole repo-relative
|
|
||||||
# path, so use a leading .* to match a file in any directory.
|
|
||||||
IGNORED: |
|
|
||||||
package-lock\.json
|
|
||||||
composer\.lock
|
|
||||||
tests/.*
|
|
||||||
e2e/.*
|
|
||||||
.*\.(test|spec)\.(ts|js|vue)
|
|
||||||
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
# An empty list yields "^()$", which matches no filename. grep exits
|
|
||||||
# 1 on an empty list, so swallow that rather than fail the step.
|
|
||||||
join() { { grep -vE '^[[:space:]]*$' || true; } | paste -sd'|' -; }
|
|
||||||
ignored="^($(join <<<"$IGNORED"))$"
|
|
||||||
|
|
||||||
total=$(gh api --paginate "repos/$REPO/pulls/$PR/files" \
|
|
||||||
--jq '.[] | [.filename, .additions + .deletions] | @tsv' |
|
|
||||||
awk -F'\t' -v ignored="$ignored" '
|
|
||||||
$1 ~ ignored { next }
|
|
||||||
{ n += $2 }
|
|
||||||
END { print n+0 }')
|
|
||||||
echo "total=$total" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "Countable diff size: $total line(s)"
|
|
||||||
|
|
||||||
- name: "Small patch (denounced users still blocked)"
|
|
||||||
if: fromJSON(steps.size.outputs.total) <= 50
|
|
||||||
uses: mitchellh/vouch/action/check-pr@v1.5.0
|
|
||||||
with:
|
|
||||||
pr-number: ${{ github.event.pull_request.number || github.event.issue.number }}
|
|
||||||
auto-close: true
|
|
||||||
require-vouch: false
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: "Full vouch required"
|
|
||||||
if: fromJSON(steps.size.outputs.total) > 50
|
|
||||||
uses: mitchellh/vouch/action/check-pr@v1.5.0
|
|
||||||
with:
|
|
||||||
pr-number: ${{ github.event.pull_request.number || github.event.issue.number }}
|
|
||||||
auto-close: true
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
33
.github/workflows/vouch-manage-by-discussion.yml
vendored
33
.github/workflows/vouch-manage-by-discussion.yml
vendored
@@ -1,33 +0,0 @@
|
|||||||
name: Vouch (manage by discussion)
|
|
||||||
|
|
||||||
# Same commands as vouch-manage-by-issue.yml, but for discussion comments.
|
|
||||||
|
|
||||||
on:
|
|
||||||
discussion_comment:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: vouch-manage
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
discussions: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
manage:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 5
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: "Checkout code"
|
|
||||||
uses: actions/checkout@v7
|
|
||||||
|
|
||||||
- name: "Apply vouch command"
|
|
||||||
uses: mitchellh/vouch/action/manage-by-discussion@v1.5.0
|
|
||||||
with:
|
|
||||||
discussion-number: ${{ github.event.discussion.number }}
|
|
||||||
comment-node-id: ${{ github.event.comment.node_id }}
|
|
||||||
roles: admin,maintain,write
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
35
.github/workflows/vouch-manage-by-issue.yml
vendored
35
.github/workflows/vouch-manage-by-issue.yml
vendored
@@ -1,35 +0,0 @@
|
|||||||
name: Vouch (manage by issue)
|
|
||||||
|
|
||||||
# Maintainers comment "vouch @user", "unvouch @user" or "denounce @user <reason>"
|
|
||||||
# on any issue or pull request, and this workflow updates .github/VOUCHED.td.
|
|
||||||
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: vouch-manage
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
manage:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 5
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: "Checkout code"
|
|
||||||
uses: actions/checkout@v7
|
|
||||||
|
|
||||||
- name: "Apply vouch command"
|
|
||||||
uses: mitchellh/vouch/action/manage-by-issue@v1.5.0
|
|
||||||
with:
|
|
||||||
issue-id: ${{ github.event.issue.number }}
|
|
||||||
comment-id: ${{ github.event.comment.id }}
|
|
||||||
roles: admin,maintain,write
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
@@ -12,22 +12,6 @@ In order to keep the issues of the repository clean we decided to only use them
|
|||||||
|
|
||||||
To respect your time and help us manage contributions effectively, please open an issue or start a discussion and wait for approval before submitting a pull request (PR). This does not apply to tiny fixes or changes however, please keep in mind that we might not merge PRs for various reasons.
|
To respect your time and help us manage contributions effectively, please open an issue or start a discussion and wait for approval before submitting a pull request (PR). This does not apply to tiny fixes or changes however, please keep in mind that we might not merge PRs for various reasons.
|
||||||
|
|
||||||
### Vouched contributors
|
|
||||||
|
|
||||||
Pull requests from authors who are not vouched are closed automatically. This lets us keep up with the volume of AI slop pull requests without a maintainer having to triage every one of them by hand.
|
|
||||||
|
|
||||||
Your pull request is not affected if any of the following applies:
|
|
||||||
|
|
||||||
- You have write access to this repository.
|
|
||||||
- Someone with write access has vouched for you. The list lives in [.github/VOUCHED.td](.github/VOUCHED.td).
|
|
||||||
- Your pull request changes 50 lines or fewer. Test files and lockfiles do not count towards that number, so a small fix that comes with tests still qualifies.
|
|
||||||
|
|
||||||
To get vouched, open an issue or discussion before you start and explain how you intend to implement the change. We will discuss the approach with you, and only once we have agreed on the implementation does a maintainer comment `vouch @your-handle`, which puts you on the list from then on.
|
|
||||||
|
|
||||||
Being vouched only stops your pull requests from being closed automatically. [Only work on approved issues](#only-work-on-approved-issues) still applies to every pull request you send.
|
|
||||||
|
|
||||||
Contributors who abuse this are denounced, and their pull requests are closed regardless of size.
|
|
||||||
|
|
||||||
### Contributor License Agreement
|
### Contributor License Agreement
|
||||||
|
|
||||||
You'll also notice that we’ve set up a [Contributor License Agreement (CLA)](https://cla-assistant.io/solidtime-io/solidtime), which must be signed before any PR can be merged. Don’t worry - the process is quick and only takes a few clicks.
|
You'll also notice that we’ve set up a [Contributor License Agreement (CLA)](https://cla-assistant.io/solidtime-io/solidtime), which must be signed before any PR can be merged. Don’t worry - the process is quick and only takes a few clicks.
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ Please open an issue or start a discussion and wait for approval before submitti
|
|||||||
|
|
||||||
**If you submit an AI slop pull request (especially without following the proper procedure), you will be banned from future contributions to solidtime.**
|
**If you submit an AI slop pull request (especially without following the proper procedure), you will be banned from future contributions to solidtime.**
|
||||||
|
|
||||||
To keep that manageable, pull requests from authors who are not vouched are closed automatically, unless they change 50 lines or fewer. To get vouched, open an issue or discussion first and explain how you intend to implement the change. Once we have agreed on the approach, we vouch for you. See [Vouched contributors](./CONTRIBUTING.md#vouched-contributors).
|
|
||||||
|
|
||||||
Please read the [CONTRIBUTING.md](./CONTRIBUTING.md) before sumbitting a Pull Request.
|
Please read the [CONTRIBUTING.md](./CONTRIBUTING.md) before sumbitting a Pull Request.
|
||||||
|
|
||||||
We do accept contributions in the [documentation repository](https://github.com/solidtime-io/docs) f.e. to add new self-hosting guides.
|
We do accept contributions in the [documentation repository](https://github.com/solidtime-io/docs) f.e. to add new self-hosting guides.
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ class PermissionStore
|
|||||||
'invoices:update',
|
'invoices:update',
|
||||||
'invoices:download',
|
'invoices:download',
|
||||||
'invoices:delete',
|
'invoices:delete',
|
||||||
|
'invoice-recipients:view',
|
||||||
|
'invoice-recipients:create',
|
||||||
|
'invoice-recipients:update',
|
||||||
|
'invoice-recipients:delete',
|
||||||
'invoice-settings:view',
|
'invoice-settings:view',
|
||||||
'invoice-settings:update',
|
'invoice-settings:update',
|
||||||
],
|
],
|
||||||
@@ -147,6 +151,10 @@ class PermissionStore
|
|||||||
'invoices:update',
|
'invoices:update',
|
||||||
'invoices:download',
|
'invoices:download',
|
||||||
'invoices:delete',
|
'invoices:delete',
|
||||||
|
'invoice-recipients:view',
|
||||||
|
'invoice-recipients:create',
|
||||||
|
'invoice-recipients:update',
|
||||||
|
'invoice-recipients:delete',
|
||||||
'invoice-settings:view',
|
'invoice-settings:view',
|
||||||
'invoice-settings:update',
|
'invoice-settings:update',
|
||||||
],
|
],
|
||||||
@@ -203,6 +211,10 @@ class PermissionStore
|
|||||||
'invoices:update',
|
'invoices:update',
|
||||||
'invoices:download',
|
'invoices:download',
|
||||||
'invoices:delete',
|
'invoices:delete',
|
||||||
|
'invoice-recipients:view',
|
||||||
|
'invoice-recipients:create',
|
||||||
|
'invoice-recipients:update',
|
||||||
|
'invoice-recipients:delete',
|
||||||
'invoice-settings:view',
|
'invoice-settings:view',
|
||||||
'invoice-settings:update',
|
'invoice-settings:update',
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Billing": {
|
"Billing": {
|
||||||
"repository": "solidtime-io/extension-billing",
|
"repository": "solidtime-io/extension-billing",
|
||||||
"ref": "v0.0.3"
|
"ref": "v0.0.4"
|
||||||
},
|
},
|
||||||
"Services": {
|
"Services": {
|
||||||
"repository": "solidtime-io/extension-services",
|
"repository": "solidtime-io/extension-services",
|
||||||
@@ -9,6 +9,6 @@
|
|||||||
},
|
},
|
||||||
"Invoicing": {
|
"Invoicing": {
|
||||||
"repository": "solidtime-io/extension-invoicing",
|
"repository": "solidtime-io/extension-invoicing",
|
||||||
"ref": "v0.0.1"
|
"ref": "feature/recipients"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2193
package-lock.json
generated
2193
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -57,7 +57,7 @@
|
|||||||
"@floating-ui/core": "^1.7.5",
|
"@floating-ui/core": "^1.7.5",
|
||||||
"@floating-ui/vue": "^1.1.11",
|
"@floating-ui/vue": "^1.1.11",
|
||||||
"@heroicons/vue": "^2.2.0",
|
"@heroicons/vue": "^2.2.0",
|
||||||
"@lucide/vue": "^1.14.0",
|
"@lucide/vue": "^1.28.0",
|
||||||
"@rushstack/eslint-patch": "^1.16.1",
|
"@rushstack/eslint-patch": "^1.16.1",
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tanstack/vue-form": "^1.32.0",
|
"@tanstack/vue-form": "^1.32.0",
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
"@tanstack/vue-virtual": "^3.13.24",
|
"@tanstack/vue-virtual": "^3.13.24",
|
||||||
"@vue/eslint-config-prettier": "^10.2.0",
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
"@vue/eslint-config-typescript": "^14.7.0",
|
"@vue/eslint-config-typescript": "^14.7.0",
|
||||||
"@vueuse/core": "^14.3.0",
|
"@vueuse/core": "^14.4.0",
|
||||||
"@vueuse/integrations": "^14.3.0",
|
"@vueuse/integrations": "^14.3.0",
|
||||||
"@zodios/core": "^10.9.6",
|
"@zodios/core": "^10.9.6",
|
||||||
"chroma-js": "^3.2.0",
|
"chroma-js": "^3.2.0",
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
"parse-duration": "^2.1.6",
|
"parse-duration": "^2.1.6",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
"radix-vue": "^1.9.17",
|
"radix-vue": "^1.9.17",
|
||||||
"reka-ui": "^2.9.7",
|
"reka-ui": "^2.10.1",
|
||||||
"tailwind-merge": "^2.6.1",
|
"tailwind-merge": "^2.6.1",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"vue-draggable-plus": "^0.6.1",
|
"vue-draggable-plus": "^0.6.1",
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ export type DetailedInvoiceResponse = ZodiosResponseByAlias<SolidTimeApi, 'getIn
|
|||||||
export type DetailedInvoice = DetailedInvoiceResponse['data'];
|
export type DetailedInvoice = DetailedInvoiceResponse['data'];
|
||||||
|
|
||||||
export type InvoiceIndexEntry = ZodiosResponseByAlias<SolidTimeApi, 'getInvoices'>['data'][0];
|
export type InvoiceIndexEntry = ZodiosResponseByAlias<SolidTimeApi, 'getInvoices'>['data'][0];
|
||||||
|
export type InvoiceRecipient = ZodiosResponseByAlias<SolidTimeApi, 'getInvoiceRecipients'>['data'][0];
|
||||||
|
export type InvoiceRecipientBody = ZodiosBodyByAlias<SolidTimeApi, 'createInvoiceRecipient'>;
|
||||||
|
|
||||||
export type UpdateInvoiceSettings = ZodiosBodyByAlias<SolidTimeApi, 'updateInvoiceSettings'>;
|
export type UpdateInvoiceSettings = ZodiosBodyByAlias<SolidTimeApi, 'updateInvoiceSettings'>;
|
||||||
|
|
||||||
|
|||||||
@@ -45,14 +45,54 @@ const InvitationResource = z
|
|||||||
const InvitationStoreRequest = z
|
const InvitationStoreRequest = z
|
||||||
.object({ email: z.string().email(), role: z.enum(['admin', 'manager', 'employee']) })
|
.object({ email: z.string().email(), role: z.enum(['admin', 'manager', 'employee']) })
|
||||||
.passthrough();
|
.passthrough();
|
||||||
|
const InvoiceRecipientResource = z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
organization_id: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
vatin: z.union([z.string(), z.null()]),
|
||||||
|
address_line_1: z.union([z.string(), z.null()]),
|
||||||
|
address_line_2: z.union([z.string(), z.null()]),
|
||||||
|
address_line_3: z.union([z.string(), z.null()]),
|
||||||
|
address_post_code: z.union([z.string(), z.null()]),
|
||||||
|
address_city: z.union([z.string(), z.null()]),
|
||||||
|
address_country: z.union([z.string(), z.null()]),
|
||||||
|
phone: z.union([z.string(), z.null()]),
|
||||||
|
email: z.union([z.string(), z.null()]),
|
||||||
|
is_archived: z.boolean(),
|
||||||
|
archived_at: z.union([z.string(), z.null()]),
|
||||||
|
invoices_count: z.number().int(),
|
||||||
|
has_non_draft_invoices: z.boolean(),
|
||||||
|
created_at: z.union([z.string(), z.null()]),
|
||||||
|
updated_at: z.union([z.string(), z.null()]),
|
||||||
|
})
|
||||||
|
.passthrough();
|
||||||
|
const InvoiceRecipientCollection = z.array(InvoiceRecipientResource);
|
||||||
|
const InvoiceRecipientRequest = z
|
||||||
|
.object({
|
||||||
|
name: z.string(),
|
||||||
|
vatin: z.union([z.string(), z.null()]).optional(),
|
||||||
|
address_line_1: z.union([z.string(), z.null()]).optional(),
|
||||||
|
address_line_2: z.union([z.string(), z.null()]).optional(),
|
||||||
|
address_line_3: z.union([z.string(), z.null()]).optional(),
|
||||||
|
address_post_code: z.union([z.string(), z.null()]).optional(),
|
||||||
|
address_city: z.union([z.string(), z.null()]).optional(),
|
||||||
|
address_country: z.union([z.string(), z.null()]).optional(),
|
||||||
|
phone: z.union([z.string(), z.null()]).optional(),
|
||||||
|
email: z.union([z.string(), z.null()]).optional(),
|
||||||
|
is_archived: z.boolean().optional(),
|
||||||
|
})
|
||||||
|
.passthrough();
|
||||||
const InvoiceResource = z
|
const InvoiceResource = z
|
||||||
.object({
|
.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
organization_id: z.string(),
|
organization_id: z.string(),
|
||||||
|
invoice_recipient_id: z.string(),
|
||||||
reference: z.string(),
|
reference: z.string(),
|
||||||
seller_name: z.string(),
|
seller_name: z.string(),
|
||||||
buyer_name: z.string(),
|
recipient: z.string(),
|
||||||
status: z.string(),
|
status: z.string(),
|
||||||
|
status_label: z.string(),
|
||||||
date: z.string(),
|
date: z.string(),
|
||||||
due_at: z.string(),
|
due_at: z.string(),
|
||||||
paid_date: z.string(),
|
paid_date: z.string(),
|
||||||
@@ -76,16 +116,7 @@ const InvoiceStoreRequest = z
|
|||||||
seller_address_country: z.union([z.string(), z.null()]).optional(),
|
seller_address_country: z.union([z.string(), z.null()]).optional(),
|
||||||
seller_phone: z.union([z.string(), z.null()]).optional(),
|
seller_phone: z.union([z.string(), z.null()]).optional(),
|
||||||
seller_email: z.union([z.string(), z.null()]).optional(),
|
seller_email: z.union([z.string(), z.null()]).optional(),
|
||||||
buyer_name: z.string(),
|
invoice_recipient_id: z.string(),
|
||||||
buyer_vatin: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_address_line_1: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_address_line_2: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_address_line_3: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_address_post_code: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_address_city: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_address_country: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_phone: z.union([z.string(), z.null()]).optional(),
|
|
||||||
buyer_email: z.union([z.string(), z.null()]).optional(),
|
|
||||||
date: z.string(),
|
date: z.string(),
|
||||||
billing_period_start: z.union([z.string(), z.null()]).optional(),
|
billing_period_start: z.union([z.string(), z.null()]).optional(),
|
||||||
billing_period_end: z.union([z.string(), z.null()]).optional(),
|
billing_period_end: z.union([z.string(), z.null()]).optional(),
|
||||||
@@ -130,6 +161,7 @@ const DetailedInvoiceResource = z
|
|||||||
.object({
|
.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
organization_id: z.string(),
|
organization_id: z.string(),
|
||||||
|
invoice_recipient_id: z.string(),
|
||||||
reference: z.string(),
|
reference: z.string(),
|
||||||
seller_name: z.string(),
|
seller_name: z.string(),
|
||||||
seller_vatin: z.string(),
|
seller_vatin: z.string(),
|
||||||
@@ -141,16 +173,7 @@ const DetailedInvoiceResource = z
|
|||||||
seller_address_country: z.string(),
|
seller_address_country: z.string(),
|
||||||
seller_phone: z.string(),
|
seller_phone: z.string(),
|
||||||
seller_email: z.string(),
|
seller_email: z.string(),
|
||||||
buyer_name: z.string(),
|
recipient: InvoiceRecipientResource,
|
||||||
buyer_vatin: z.string(),
|
|
||||||
buyer_address_line_1: z.string(),
|
|
||||||
buyer_address_line_2: z.string(),
|
|
||||||
buyer_address_line_3: z.string(),
|
|
||||||
buyer_address_post_code: z.string(),
|
|
||||||
buyer_address_city: z.string(),
|
|
||||||
buyer_address_country: z.string(),
|
|
||||||
buyer_phone: z.string(),
|
|
||||||
buyer_email: z.string(),
|
|
||||||
paid_date: z.string(),
|
paid_date: z.string(),
|
||||||
due_at: z.string(),
|
due_at: z.string(),
|
||||||
discount_type: z.string(),
|
discount_type: z.string(),
|
||||||
@@ -171,7 +194,7 @@ const DetailedInvoiceResource = z
|
|||||||
entries: z.array(InvoiceEntryResource),
|
entries: z.array(InvoiceEntryResource),
|
||||||
})
|
})
|
||||||
.passthrough();
|
.passthrough();
|
||||||
const InvoiceStatus = z.enum(['draft', 'sent', 'cancelled']);
|
const InvoiceStatus = z.enum(['draft', 'sent', 'paid', 'cancelled']);
|
||||||
const InvoiceUpdateRequest = z
|
const InvoiceUpdateRequest = z
|
||||||
.object({
|
.object({
|
||||||
status: InvoiceStatus,
|
status: InvoiceStatus,
|
||||||
@@ -187,16 +210,7 @@ const InvoiceUpdateRequest = z
|
|||||||
seller_address_country: z.union([z.string(), z.null()]),
|
seller_address_country: z.union([z.string(), z.null()]),
|
||||||
seller_phone: z.union([z.string(), z.null()]),
|
seller_phone: z.union([z.string(), z.null()]),
|
||||||
seller_email: z.union([z.string(), z.null()]),
|
seller_email: z.union([z.string(), z.null()]),
|
||||||
buyer_name: z.string(),
|
invoice_recipient_id: z.string(),
|
||||||
buyer_vatin: z.union([z.string(), z.null()]),
|
|
||||||
buyer_address_line_1: z.union([z.string(), z.null()]),
|
|
||||||
buyer_address_line_2: z.union([z.string(), z.null()]),
|
|
||||||
buyer_address_line_3: z.union([z.string(), z.null()]),
|
|
||||||
buyer_address_post_code: z.union([z.string(), z.null()]),
|
|
||||||
buyer_address_city: z.union([z.string(), z.null()]),
|
|
||||||
buyer_address_country: z.union([z.string(), z.null()]),
|
|
||||||
buyer_phone: z.union([z.string(), z.null()]),
|
|
||||||
buyer_email: z.union([z.string(), z.null()]),
|
|
||||||
date: z.string(),
|
date: z.string(),
|
||||||
billing_period_start: z.union([z.string(), z.null()]),
|
billing_period_start: z.union([z.string(), z.null()]),
|
||||||
billing_period_end: z.union([z.string(), z.null()]),
|
billing_period_end: z.union([z.string(), z.null()]),
|
||||||
@@ -1885,6 +1899,125 @@ const endpoints = makeApi([
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
method: 'get',
|
||||||
|
path: '/v1/organizations/:organization/invoice-recipients',
|
||||||
|
alias: 'getInvoiceRecipients',
|
||||||
|
requestFormat: 'json',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'organization',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
response: z.object({ data: InvoiceRecipientCollection }).passthrough(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'post',
|
||||||
|
path: '/v1/organizations/:organization/invoice-recipients',
|
||||||
|
alias: 'createInvoiceRecipient',
|
||||||
|
requestFormat: 'json',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'body',
|
||||||
|
type: 'Body',
|
||||||
|
schema: InvoiceRecipientRequest,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'organization',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
response: z.object({ data: InvoiceRecipientResource }).passthrough(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'get',
|
||||||
|
path: '/v1/organizations/:organization/invoice-recipients/:invoiceRecipient',
|
||||||
|
alias: 'getInvoiceRecipient',
|
||||||
|
requestFormat: 'json',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'organization',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'invoiceRecipient',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
response: z.object({ data: InvoiceRecipientResource }).passthrough(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'put',
|
||||||
|
path: '/v1/organizations/:organization/invoice-recipients/:invoiceRecipient',
|
||||||
|
alias: 'updateInvoiceRecipient',
|
||||||
|
requestFormat: 'json',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'body',
|
||||||
|
type: 'Body',
|
||||||
|
schema: InvoiceRecipientRequest,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'organization',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'invoiceRecipient',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
response: z.object({ data: InvoiceRecipientResource }).passthrough(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'post',
|
||||||
|
path: '/v1/organizations/:organization/invoice-recipients/:invoiceRecipient/duplicate',
|
||||||
|
alias: 'duplicateInvoiceRecipient',
|
||||||
|
requestFormat: 'json',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'body',
|
||||||
|
type: 'Body',
|
||||||
|
schema: InvoiceRecipientRequest,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'organization',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'invoiceRecipient',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
response: z.object({ data: InvoiceRecipientResource }).passthrough(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: 'delete',
|
||||||
|
path: '/v1/organizations/:organization/invoice-recipients/:invoiceRecipient',
|
||||||
|
alias: 'deleteInvoiceRecipient',
|
||||||
|
requestFormat: 'json',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'organization',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'invoiceRecipient',
|
||||||
|
type: 'Path',
|
||||||
|
schema: z.string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
response: z.void(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
method: 'get',
|
method: 'get',
|
||||||
path: '/v1/organizations/:organization/invoices',
|
path: '/v1/organizations/:organization/invoices',
|
||||||
@@ -1901,6 +2034,11 @@ const endpoints = makeApi([
|
|||||||
type: 'Query',
|
type: 'Query',
|
||||||
schema: z.number().int().gte(1).lte(2147483647).optional(),
|
schema: z.number().int().gte(1).lte(2147483647).optional(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
type: 'Query',
|
||||||
|
schema: InvoiceStatus.optional(),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
response: z.object({ data: InvoiceCollection }).passthrough(),
|
response: z.object({ data: InvoiceCollection }).passthrough(),
|
||||||
errors: [
|
errors: [
|
||||||
|
|||||||
25
resources/js/packages/ui/src/combobox/Combobox.vue
Normal file
25
resources/js/packages/ui/src/combobox/Combobox.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxRootEmits, ComboboxRootProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { ComboboxRoot, useForwardPropsEmits } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxRootProps & { class?: HTMLAttributes['class'] }>();
|
||||||
|
const emits = defineEmits<ComboboxRootEmits>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- Keep the trigger inside this root. Reka treats anything within the root
|
||||||
|
element as "not outside", so it suppresses its own dismissal for trigger
|
||||||
|
clicks and ComboboxInput's blur-close ignores them. Putting the trigger
|
||||||
|
in a separate Popover instead gives two competing open states, and the
|
||||||
|
popover then closes on mousedown and reopens on the following click. -->
|
||||||
|
<ComboboxRoot v-slot="slotProps" v-bind="forwarded" :class="cn('min-w-0', props.class)">
|
||||||
|
<slot v-bind="slotProps" />
|
||||||
|
</ComboboxRoot>
|
||||||
|
</template>
|
||||||
19
resources/js/packages/ui/src/combobox/ComboboxAnchor.vue
Normal file
19
resources/js/packages/ui/src/combobox/ComboboxAnchor.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxAnchorProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { ComboboxAnchor, useForwardProps } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxAnchor v-bind="forwarded" :class="cn('w-full', props.class)">
|
||||||
|
<slot />
|
||||||
|
</ComboboxAnchor>
|
||||||
|
</template>
|
||||||
35
resources/js/packages/ui/src/combobox/ComboboxInput.vue
Normal file
35
resources/js/packages/ui/src/combobox/ComboboxInput.vue
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxInputEmits, ComboboxInputProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { Search } from '@lucide/vue';
|
||||||
|
import { ComboboxInput, useForwardPropsEmits } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxInputProps & { class?: HTMLAttributes['class'] }>();
|
||||||
|
const emits = defineEmits<ComboboxInputEmits>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative items-center border-b border-card-background-separator">
|
||||||
|
<ComboboxInput
|
||||||
|
v-bind="{ ...$attrs, ...forwarded }"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'h-10 w-full border-0 rounded-none bg-transparent pl-9 pr-3 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:ring-0',
|
||||||
|
props.class
|
||||||
|
)
|
||||||
|
" />
|
||||||
|
<span class="absolute start-0 inset-y-0 flex items-center justify-center px-3">
|
||||||
|
<Search class="size-4 text-text-tertiary" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
27
resources/js/packages/ui/src/combobox/ComboboxItem.vue
Normal file
27
resources/js/packages/ui/src/combobox/ComboboxItem.vue
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { ComboboxItem, useForwardPropsEmits } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>();
|
||||||
|
const emits = defineEmits<ComboboxItemEmits>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxItem
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'flex w-full cursor-default items-center rounded-md px-2 py-1.5 text-sm text-text-primary data-[highlighted]:bg-card-background-active',
|
||||||
|
props.class
|
||||||
|
)
|
||||||
|
">
|
||||||
|
<slot />
|
||||||
|
</ComboboxItem>
|
||||||
|
</template>
|
||||||
41
resources/js/packages/ui/src/combobox/ComboboxList.vue
Normal file
41
resources/js/packages/ui/src/combobox/ComboboxList.vue
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { ComboboxContent, ComboboxPortal, useForwardPropsEmits } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(),
|
||||||
|
{
|
||||||
|
position: 'popper',
|
||||||
|
align: 'start',
|
||||||
|
sideOffset: 4,
|
||||||
|
class: undefined,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const emits = defineEmits<ComboboxContentEmits>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxPortal>
|
||||||
|
<ComboboxContent
|
||||||
|
v-bind="{ ...$attrs, ...forwarded }"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'z-50 w-[--reka-popper-anchor-width] min-w-60 overflow-hidden rounded-lg border border-popover-border bg-popover text-popover-foreground shadow-dropdown outline-none origin-[var(--reka-combobox-content-transform-origin)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
|
props.class
|
||||||
|
)
|
||||||
|
">
|
||||||
|
<slot />
|
||||||
|
</ComboboxContent>
|
||||||
|
</ComboboxPortal>
|
||||||
|
</template>
|
||||||
19
resources/js/packages/ui/src/combobox/ComboboxSeparator.vue
Normal file
19
resources/js/packages/ui/src/combobox/ComboboxSeparator.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxSeparatorProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { ComboboxSeparator, useForwardProps } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxSeparator
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('my-1 h-px bg-card-background-separator', props.class)" />
|
||||||
|
</template>
|
||||||
29
resources/js/packages/ui/src/combobox/ComboboxTrigger.vue
Normal file
29
resources/js/packages/ui/src/combobox/ComboboxTrigger.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxTriggerProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { ComboboxTrigger, useForwardProps } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!-- Reka hardcodes tabindex="-1" here because it expects a ComboboxInput
|
||||||
|
next to the trigger in the anchor to be the focusable control. Our input
|
||||||
|
lives inside ComboboxList, so this trigger is the control and has to be
|
||||||
|
tabbable. tabindex is a fallthrough attr, which Vue applies after Reka's
|
||||||
|
own props and therefore wins.
|
||||||
|
|
||||||
|
Reka also hardcodes aria-label="Show popup", which would otherwise be
|
||||||
|
the accessible name. Pass :aria-label on the child element (it wins
|
||||||
|
again, because Slot merges child props over attrs) to name the trigger
|
||||||
|
after its current value. -->
|
||||||
|
<ComboboxTrigger v-bind="forwarded" :class="cn(props.class)" tabindex="0">
|
||||||
|
<slot />
|
||||||
|
</ComboboxTrigger>
|
||||||
|
</template>
|
||||||
38
resources/js/packages/ui/src/combobox/ComboboxViewport.vue
Normal file
38
resources/js/packages/ui/src/combobox/ComboboxViewport.vue
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxViewportProps } from 'reka-ui';
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { reactiveOmit } from '@vueuse/core';
|
||||||
|
import { ComboboxViewport, useForwardProps } from 'reka-ui';
|
||||||
|
import { cn } from '../utils/cn';
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxViewportProps & { class?: HTMLAttributes['class'] }>();
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, 'class');
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxViewport
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('ui-combobox-viewport max-h-60 overflow-y-auto p-2', props.class)">
|
||||||
|
<slot />
|
||||||
|
</ComboboxViewport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Reka's ComboboxViewport injects a global style that hides scrollbars; the
|
||||||
|
attribute+class selector below is more specific and restores them. */
|
||||||
|
[data-reka-combobox-viewport].ui-combobox-viewport {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
-ms-overflow-style: auto;
|
||||||
|
}
|
||||||
|
[data-reka-combobox-viewport].ui-combobox-viewport::-webkit-scrollbar {
|
||||||
|
display: block;
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
[data-reka-combobox-viewport].ui-combobox-viewport::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(127 127 127 / 0.4);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
9
resources/js/packages/ui/src/combobox/index.ts
Normal file
9
resources/js/packages/ui/src/combobox/index.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export { default as Combobox } from './Combobox.vue';
|
||||||
|
export { default as ComboboxAnchor } from './ComboboxAnchor.vue';
|
||||||
|
export { default as ComboboxInput } from './ComboboxInput.vue';
|
||||||
|
export { default as ComboboxItem } from './ComboboxItem.vue';
|
||||||
|
export { default as ComboboxList } from './ComboboxList.vue';
|
||||||
|
export { default as ComboboxSeparator } from './ComboboxSeparator.vue';
|
||||||
|
export { default as ComboboxTrigger } from './ComboboxTrigger.vue';
|
||||||
|
export { default as ComboboxViewport } from './ComboboxViewport.vue';
|
||||||
|
export { ComboboxVirtualizer } from 'reka-ui';
|
||||||
@@ -57,6 +57,16 @@ import {
|
|||||||
CalendarNextButton,
|
CalendarNextButton,
|
||||||
CalendarPrevButton,
|
CalendarPrevButton,
|
||||||
} from './calendar/index';
|
} from './calendar/index';
|
||||||
|
import {
|
||||||
|
Combobox,
|
||||||
|
ComboboxAnchor,
|
||||||
|
ComboboxInput,
|
||||||
|
ComboboxItem,
|
||||||
|
ComboboxList,
|
||||||
|
ComboboxSeparator,
|
||||||
|
ComboboxTrigger,
|
||||||
|
ComboboxViewport,
|
||||||
|
} from './combobox/index';
|
||||||
import { CommandPalette } from './CommandPalette/index';
|
import { CommandPalette } from './CommandPalette/index';
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
@@ -176,6 +186,14 @@ export {
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
color,
|
color,
|
||||||
|
Combobox,
|
||||||
|
ComboboxAnchor,
|
||||||
|
ComboboxInput,
|
||||||
|
ComboboxItem,
|
||||||
|
ComboboxList,
|
||||||
|
ComboboxSeparator,
|
||||||
|
ComboboxTrigger,
|
||||||
|
ComboboxViewport,
|
||||||
CommandPalette,
|
CommandPalette,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
ContextMenuCheckboxItem,
|
ContextMenuCheckboxItem,
|
||||||
|
|||||||
Reference in New Issue
Block a user