diff --git a/FieldListing/035697b8-1d74-40ec-8833-c6c9865ae9d9.json b/FieldListing/035697b8-1d74-40ec-8833-c6c9865ae9d9.json new file mode 100644 index 0000000..c9f391c --- /dev/null +++ b/FieldListing/035697b8-1d74-40ec-8833-c6c9865ae9d9.json @@ -0,0 +1,64 @@ +{ + "data": { + "meta": { + "adoptsFrom": { + "name": "FieldListing", + "module": "https://realms-staging.stack.cards/catalog/catalog-app/listing/listing" + } + }, + "type": "card", + "attributes": { + "name": "Address字段定义及显示组件", + "images": [], + "summary": "The Address definition provides a structured representation of mailing addresses, encapsulating common address components such as address lines, city, state, postal code, country, and PO box number. It enables the display of addresses both as a summarized label and as detailed address rows. The primary purpose is to standardize and facilitate the display, storage, and manipulation of address data within applications, offering components for visual presentation with icons and embedded detailed views.", + "cardInfo": { + "name": null, + "notes": null, + "summary": null, + "cardThumbnailURL": null + } + }, + "relationships": { + "skills": { + "links": { + "self": null + } + }, + "tags.0": { + "links": { + "self": "https://realms-staging.stack.cards/catalog/Tag/ed5a1a3f-0dbf-47b5-b2a6-d88b0d2a7642" + } + }, + "license": { + "links": { + "self": "https://realms-staging.stack.cards/catalog/License/4c5a023b-a72c-4f90-930b-da60a1de5b2d" + } + }, + "specs.0": { + "links": { + "self": "../Spec/6ee7a758-9291-4e72-92dc-e0a5ab2676a8" + } + }, + "examples": { + "links": { + "self": null + } + }, + "publisher": { + "links": { + "self": null + } + }, + "categories.0": { + "links": { + "self": "https://realms-staging.stack.cards/catalog/Category/home-living" + } + }, + "cardInfo.theme": { + "links": { + "self": null + } + } + } + } +} \ No newline at end of file diff --git a/Spec/6ee7a758-9291-4e72-92dc-e0a5ab2676a8.json b/Spec/6ee7a758-9291-4e72-92dc-e0a5ab2676a8.json new file mode 100644 index 0000000..2e2e5be --- /dev/null +++ b/Spec/6ee7a758-9291-4e72-92dc-e0a5ab2676a8.json @@ -0,0 +1,63 @@ +{ + "data": { + "meta": { + "fields": { + "containedExamples": [ + { + "adoptsFrom": { + "module": "../address", + "name": "Address" + } + } + ] + }, + "adoptsFrom": { + "name": "Spec", + "module": "https://cardstack.com/base/spec" + } + }, + "type": "card", + "attributes": { + "ref": { + "name": "Address", + "module": "../address" + }, + "title": "Address", + "readMe": "# Address Field Definition\n\nThe `Address` field definition provides a reusable way to represent physical addresses within a Boxel application. It allows you to capture various address components such as street, city, state, postal code, and country, and automatically compute a formatted full address string.\n\n## Import\nTo use the `Address` field in your code, import it from the `../address` module:\n\n```javascript\nimport { Address } from '../address';\n```\n\n## Define Field\nYou can define an `Address` field within a card definition using the `contains` method:\n\n```javascript\nexport class MyCard extends CardDef {\n @field address = contains(Address);\n}\n```\n\n## Invoke Template\nIn your card templates, you can display the address field using the `@fields.address` syntax:\n\n```hbs\n
\n <@fields.address />\n
\n```\n\n## Dependencies\nThe `Address` field definition has the following dependencies:\n\n- Imports `CountryField` from `./country`\n- Uses `EntityDisplayWithIcon` and `MapPinIcon` components from `./components/entity-icon-display`\n\n## Usage and Examples\nHere's an example of how you might use the `Address` field in your application:\n\n```javascript\nexport class UserProfile extends CardDef {\n @field address = contains(Address);\n}\n```\n\nIn the template for the `UserProfile` card:\n\n```hbs\n
\n

User Details

\n
\n

Address

\n <@fields.address />\n
\n
\n```\n\nThe `Address` field will automatically compute a formatted full address string based on the individual address components, and display it in the template.", + "cardInfo": { + "notes": null, + "title": null, + "description": null, + "thumbnailURL": null + }, + "specType": "field", + "description": null, + "containedExamples": [ + { + "addressLine1": null, + "addressLine2": null, + "city": null, + "state": null, + "postalCode": null, + "country": { + "name": null, + "code": null + }, + "poBoxNumber": null + } + ] + }, + "relationships": { + "cardInfo.theme": { + "links": { + "self": null + } + }, + "linkedExamples": { + "links": { + "self": null + } + } + } + } +} \ No newline at end of file diff --git a/address.gts b/address.gts new file mode 100644 index 0000000..977d74f --- /dev/null +++ b/address.gts @@ -0,0 +1,103 @@ +import { + contains, + field, + Component, + FieldDef, +} from 'https://cardstack.com/base/card-api'; +import StringField from 'https://cardstack.com/base/string'; +import { CountryField } from './country'; +import MapPinIcon from '@cardstack/boxel-icons/map-pin'; +import EntityDisplayWithIcon from './components/entity-icon-display'; + +const x = 1; + + +function getAddressRows( + addressLine1: string | undefined, + addressLine2: string | undefined, + city: string | undefined, + state: string | undefined, + postalCode: string | undefined, + countryCode: string | undefined, + poBoxNumber: string | undefined, +): string[] { + return [ + poBoxNumber ? [`PO Box: ${poBoxNumber}`] : [], + addressLine1 ? [addressLine1] : [], + addressLine2 ? [addressLine2] : [], + [city, state, postalCode].filter(Boolean), + countryCode ? [countryCode] : [], + ] + .filter(Boolean) + .filter((r) => r.length > 0) + .map((r) => r.join(', ')); +} + +class Atom extends Component { + get label() { + return ( + [this.args.model?.city, this.args.model?.country?.code] + .filter(Boolean) + .join(', ') || '' + ); + } + +} + +export class Address extends FieldDef { + static displayName = 'Address'; + static icon = MapPinIcon; + @field addressLine1 = contains(StringField); + @field addressLine2 = contains(StringField); + @field city = contains(StringField); + @field state = contains(StringField); + @field postalCode = contains(StringField); + @field country = contains(CountryField); + @field poBoxNumber = contains(StringField); + @field fullAddress = contains(StringField, { + computeVia: function (this: Address) { + let rows = getAddressRows( + this.addressLine1, + this.addressLine2, + this.city, + this.state, + this.postalCode, + this.country?.name, + this.poBoxNumber, + ); + return rows.join(', '); + }, + }); + + static embedded = class Embedded extends Component { + get addressRows() { + return getAddressRows( + this.args.model.addressLine1, + this.args.model.addressLine2, + this.args.model.city, + this.args.model.state, + this.args.model.postalCode, + this.args.model.country?.name, + this.args.model.poBoxNumber, + ); + } + + + }; + + static atom = Atom; +}