Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create country field with dropdown edit mode #1864

Merged
merged 6 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/boxel-ui/addon/src/components/select/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const BoxelSelect: TemplateOnlyComponent<Signature> = <template>
@renderInPlace={{@renderInPlace}}
@verticalPosition={{@verticalPosition}}
@dropdownClass={{cn 'boxel-select__dropdown' @dropdownClass}}
@loadingMessage={{@loadingMessage}}
{{! We can avoid providing arguments to the triggerComponent as long as they are specified here https://github.com/cibernox/ember-power-select/blob/913c85ec82d5c6aeb80a7a3b9d9c21ca9613e900/ember-power-select/src/components/power-select.hbs#L79-L106 }}
{{! Even the custom BoxelTriggerWrapper will receive these arguments }}
@triggerComponent={{(if
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"data": {
"type": "card",
"attributes": {
"country": {
"name": null,
"code": null
},
"title": null,
"description": null,
"thumbnailURL": null
},
"meta": {
"adoptsFrom": {
"module": "../country",
"name": "CardWithCountryField"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"data": {
"type": "card",
"attributes": {
"country": {
"name": "Cambodia",
"code": "KH"
},
"title": null,
"description": null,
"thumbnailURL": null
},
"meta": {
"adoptsFrom": {
"module": "../country",
"name": "CardWithCountryField"
}
}
}
}
104 changes: 104 additions & 0 deletions packages/experiments-realm/country.gts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ import {
field,
Component,
CardDef,
FieldDef,
} from 'https://cardstack.com/base/card-api';
import StringField from 'https://cardstack.com/base/string';
import World from '@cardstack/boxel-icons/world';
import { BoxelSelect } from '@cardstack/boxel-ui/components';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { restartableTask } from 'ember-concurrency';
import type Owner from '@ember/owner';
// @ts-ignore
import countryDataFind from 'https://esm.run/[email protected]';

export class Country extends CardDef {
static displayName = 'Country';
Expand All @@ -23,3 +31,99 @@ export class Country extends CardDef {
</template>
};
}

function getCountryFlagEmoji(countryCode: string) {
const codePoints = countryCode
.toUpperCase()
.split('')
.map((char) => 127397 + char.charCodeAt(0));
return String.fromCodePoint(...codePoints);
}

interface CountryData {
code: string;
name: string;
emoji?: string;
}

class CountryFieldEdit extends Component<typeof CountryField> {
@tracked country: CountryData | undefined =
this.args.model.name && this.args.model.code
? {
name: this.args.model.name,
code: this.args.model.code,
}
: undefined;
@tracked countries: CountryData[] = [];

constructor(owner: Owner, args: any) {
super(owner, args);
this.loadCountries.perform();
}

private loadCountries = restartableTask(async () => {
this.countries = countryDataFind.Array().map((country: any) => {
return {
code: country.ISO2_CODE,
name: country.LIST_OF_NAME.ENG[0],
emoji: getCountryFlagEmoji(country.ISO2_CODE),
} as CountryData;
});
});

@action onSelectCountry(country: CountryData) {
this.country = country;
this.args.model.name = country.name;
this.args.model.code = country.code;
}

@action countryEmoji(countryCode: string) {
return this.countries?.find((country) => country.code === countryCode)
?.emoji;
}

<template>
{{#if this.loadCountries.isRunning}}
Loading countries...
{{else}}
<BoxelSelect
@placeholder={{'Choose a country'}}
@options={{this.countries}}
@selected={{this.country}}
@onChange={{this.onSelectCountry}}
as |country|
>
{{#let (this.countryEmoji country.code) as |emoji|}}
{{emoji}}
{{/let}}
{{country.name}}
</BoxelSelect>
{{/if}}
</template>
}

export class CountryField extends FieldDef {
static displayName = 'Country';
@field name = contains(StringField);
@field code = contains(StringField);
static edit = CountryFieldEdit;

static atom = class Atom extends Component<typeof this> {
<template>
{{#if @model.name}}
{{@model.name}}
{{/if}}
</template>
};
}

export class CardWithCountryField extends CardDef {
static displayName = 'Card With Country Field';
@field country = contains(CountryField);

static isolated = class Isolated extends Component<typeof this> {
<template>
<@fields.country @format='atom' />
</template>
};
}
Loading