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

feat: Annotated Text component #462

Merged
merged 16 commits into from
Aug 14, 2024
Merged

Conversation

polymorpheuz
Copy link
Collaborator

No description provided.

pronoun: "Pronoun",
};

function getShortName(name: string) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we even need it. In our reference package they do things like that.

}
}

function copyToClipboard({
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these two copy functions should travel someplace else but I have no understanding where to.

{ h: 70, s: 0, l: 29 },
];

let currentSteps = [...COLOR_STEPS];
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might wonder why am I doing that. For the tags it's perfectly fine to have the same color for for different tags. Here it's critical to not repeat the colors. More below.

const colorStep = calculateColorStep(s, currentSteps.length);
const colorData = currentSteps[colorStep];

subjectColorCache[s] = colorData;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we make sure to cache the initial allocation here

const colorData = currentSteps[colorStep];

subjectColorCache[s] = colorData;
currentSteps.splice(colorStep, 1);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

..and we get rid of that color so the random pick won't set us up to have the same color for another subject

}

// If we run out of colors, reset the list
if (currentSteps.length === 0) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a safeguard in order to keep it operational even if we ran out of colors. We shouldn't allow that though and it's better to add like +10-20 color to what we have now.

return false;
}

const defaultShortNameDictionary = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this dict, people can enter the whole thing


.annotation-subject {
display: inline-flex;
font-size: 0.6rem;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use px instead of rem

I use rem for font-sizes, but looking to change to px too

return generateColorCss(baseColor, colorData);
}

function copyText(arr: string[]) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move copy functionality and the bar to base/ in a component called BaseControlBar.vue (or similar).

let subjectColorCache = {};
let lastSeed = fields.seed.value;

function generateColorCss(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free about moving to colorTransformers or similar (if you want).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@polymorpheuz We may choose to have a file for color transformations, since they're similar across tags and annotated text

{ h: -228, s: 0, l: 22 },
{ h: 69, s: 0, l: 25 },
{ h: 70, s: 0, l: 29 },
];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think about how to extend to support more colors, maybe consider discussing this with Miffy. Right now, I'm using the Tag colors as specified in the design system.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ramedina86 I've asked Miffy a while ago on the additional colors and she pointed to the other color groups. The problem is that they don't match 😅 I was waiting for Pete being in the office to ambush him but he keeps avoiding me so far.

It seems like it's either we're going with 10 colors or an LLM is out best bet 🤣

name: "KeyValue",
type: FieldType.Object,
desc: "Value array with text/annotations. Must be a JSON string or a state reference to an array.",
default: `["This ",["is", "Verb"]," some ",["annotated", "Adjective"], ["text", "Noun"]," for those of ",["you", "Pronoun"]," who ",["like", "Verb"]," this sort of ",["thing", "Noun"],". ","And here's a ",["word", "", "#faf"]," with a fancy background but no label."]`,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go for init rather than default

@ramedina86
Copy link
Collaborator

Forgot to mention, we use conventional commits

@ramedina86 ramedina86 changed the title Annotated Text component feat: Annotated Text component Jun 19, 2024
@ramedina86
Copy link
Collaborator

Hey @polymorpheuz can you add the component to templateMap.ts? So that it's linked (unsure how you're developing right now)

@FabienArcellier this is a very interesting component if you want to have a look

Comment on lines +21 to +24
const props = defineProps<{
copyRawContent?: string;
copyStructuredContent?: string;
}>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use object definition to have runtime checks

Suggested change
const props = defineProps<{
copyRawContent?: string;
copyStructuredContent?: string;
}>();
const props = defineProps({
copyRawContent: { type: String, required: false },
copyStructuredContent: { type: String, required: false },
});

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's a broader question on how we actually define props in the project. In this case, I was following how the other components defining props. My take is to stick to one approach until we decide to go with another.

Also, I'm not sure if there's practical use of runtime checks in this case. The bar is used by us as a building block, so it's not a blackbox for a general user to leave hints to.

@ramedina86 @FabienArcellier What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good suggestion but in line with @polymorpheuz I'd like to decide on the standard and then @madeindjs can migrate all in one block :)

Comment on lines 72 to 79
try {
return document.execCommand("copy"); // Security exception may be thrown by some browsers.
} catch (ex) {
return false;
} finally {
document.body.removeChild(textarea);
document.removeEventListener("copy", copyListener, false);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document.execCommand is deprecated API (MDN). You should use Clipboard API like this

await navigator.clipboard.writeText(text);

You can even use this solution with this polyfill to support old browsers

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out!

It's not deprecated in a traditional sense. The drama around it is long and could take 5 at least more years. I went with it since I don't see it being deprecated anytime soon and it just works for any browser. It just works for any content format, so the component is easily extensible.

However, it's a nice discussion point. I couldn't find a doc on what browsers do we actually support. If we are not hitting limitations with these constraints, I have no objections on using navigator.clipboard.

cc @ramedina86 @FabienArcellier

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was an interesting read. I think let's go for the Clipboard API i.e. navigator.clipboard. It seems that the spec has finally matured and execCommand is being kept mostly for compatibility with other non-clipboard-related actions.

I think for now we only need navigator.clipboard.writeText() which has excellent support, so we won't need the polyfill. Once we work on the Rich Text Editor this might change.

Something to take into account is that writeText() only seems to work in secure contexts.

Would like to have @FabienArcellier 's opinion here too.

@@ -0,0 +1,248 @@
<template>
<div class="AnnotatedText">
<span v-for="(content, i) in fields.text.value" :key="content + i">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

content can be a number and then you can have duplicated key. I suggest to cast it to be safe

Suggested change
<span v-for="(content, i) in fields.text.value" :key="content + i">
<span v-for="(content, i) in fields.text.value" :key="String(content) + i">

Comment on lines +106 to +108
let currentSteps = [...COLOR_STEPS];
let subjectColorCache = {};
let lastSeed = fields.seed.value;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure you don't need to make them reactive ?

Suggested change
let currentSteps = [...COLOR_STEPS];
let subjectColorCache = {};
let lastSeed = fields.seed.value;
let currentSteps = ref([...COLOR_STEPS]);
let subjectColorCache = ref({});
let lastSeed = ref(fields.seed.value);

If its not refs, Vue.js can't track them and might not re-render on update (doc)

Copy link
Collaborator Author

@polymorpheuz polymorpheuz Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem that we need reactivity in this case. I am following CoreTags that seem to work in this case just as fine.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's not use reactivity that we don't need.

@ramedina86
Copy link
Collaborator

@polymorpheuz Have you looked into why CI isn't passing?

@ramedina86 ramedina86 changed the base branch from dev to feat-annotatedtext August 14, 2024 14:55
@ramedina86 ramedina86 merged commit ede9c75 into writer:feat-annotatedtext Aug 14, 2024
12 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants